先将看书做的笔记复制过来,以后再整理丰富一下
集合类有四大部分组成,分别是Map,Set,Queue和List。后三个继承自Collection
1、collection
- collection公有方法。
Add/addall 添加/将b集合中的元素全部添加到a中
Remove/removeAll 删除/删除B中所包含的元素
Retain/retainAll 进行与操作。
- lambda表达式
c.forEach(obj->System.out.println(obj));//->箭头操作符,左边是参数列表,右边是一行语句,作用是迭代输出集合内的元素。
- 迭代器Iterator
每一个集合都有自己的迭代器。
Iterator<String> iterator=c.iterator();
next()返回下一个
remove() 删除上一个next()元素//会直接修改集合
hasNext() 判断是否有下一个
Lambda 遍历迭代器可以使用 forEachRemaining
注:迭代器里的变量修改无意义,不会改变集合的值。
再注:上面的说法不准确,应该是拷贝一份元素的值。如果是对象的话,则是拷贝一份对象的引用。当通过拷贝引用修改属性时,也会反映到集合中去。
- predicate 过滤用
c.removeIf(name->name.length()<8);//removeif用来过滤符合predicate的元素
2、Set集合
Set和collection方法基本相同,唯一区别在于不能存放重复元素。如果已有该元素,则add方法返回失败,且该元素不会被添加。
- Hashset
A.特点
a.不能保证元素的顺序
b.不是同步的,即线程不安全的的
c.集合元素值可以是null
注意事项:
1通过存入对象的hashcode()和equals()判断是否是一个对象。hashcode判断存储的位置,而equals判断是否是一个对象。必须hashcode相等且equals返回true才能去重。
如果hashcode相同,equals()返回false,则导致同一个位置用链表的方式存储两个对象,导致性能下降。
如果hashcode不同,equals返回true,则导致不同位置存储两个相同对象,也不符合set的定位。
如何计算hashcode?所有参与equals对象
有一个子类linkedHashSet,可以按插入顺序遍历,通过链表维护。
2、添加可变对象时,谨慎修改
- Treeset
是sortSet的实现类,可以保证元素处于有序的状态.采用红黑树。
不允许存null,且线程不安全
a自然排序
1、自然排序添加的对象必须实现compartor接口,否则报错,且添加必须是一个类型的,否则无法比较也会报错。
2、这个类是通过compartor是否返回0判断的,应该让eqauals和comparator一致否则如果equals判断不是同一个对象但是,comparator返回0,还是会认为是一个对象,此时导致不重复的对象也无法存入。
3、当添加可变对象并修改时,导致大小发生变化,不会调整顺序,并且重复的将无法正常删除【包括原先没有修改,但是和其他元素重复的】。
b.定制排序
定制排序的对象可以不实现compartor,而是通过Treeset实现接口,或者用lambda函数式
TreeSet<Integer> tSet=new TreeSet<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o1>o2?-1:o1<o2?1:0;
}
}) ;
TreeSet<Integer> tSet=new TreeSet<Integer>((o1,o2)->{
return o1>o2?-1:o1<o2?1:0;
}) ;
- Enumset
是转为枚举类设置的,也是有序的,不允许插入null。
内部以位向量存储,因此占用内存非常小,且高效。
该类没有直接的构造器创建,需要通过类方法创建实例。
如EnumSet<season> enumSet=EnumSet.allOf(season.class);
- set总结
一般情况下hashset和treeset是经常使用的两个,但hashset的性能优于treeset,因为它维护了红黑树。除非需要保持排序时,才使用treeset。hashset之下有一个linkedhashset,它的性能在查找方面低于hashset,但是遍历上优于。
Enumset性能最好,但是只能存储枚举类。
三者都是线程不安全的,需要手动同步。通过
Set s=Collections.synchronized(new xxxset());
- List
- list接口和iterator接口
注list通过equals判断是否是一个对象。
- ArrayList和Vector
是动态数组,当数组长度不够时,会根据数组元素扩容,jdk1.8中为1.5倍。【arraylist】
未添加元素时,初始大小为0.添加一个时,默认为10.
A主要区别
- arraylist线程不安全而vector线程安全,但效率慢。
- Vector是古老的集合,从1.0开始就有。所以有一些名字很长的方法,后来为了简化编程,出现一些功能重复,但名字较短的方法 还提供了一个stack
注:通过Arrays.asList()转化的list不能改变list长度,即不支持add和remove
- linkedlist和arraylist
在于链表实现和数组实现的区别
Linkedlist还实现了deque和queue,因此也可以当做栈和
3、Queue
有两种主要方面PriorityQueue类和deque接口
1)前者是优先级队列,插入的会按照大小排序,功能类似队列,队头的先出。本质是最小堆。而最小堆就是二叉树,根节点小于
2)Deque接口
双端队列
实现是ArrayDeque,可以当做栈使用,入栈和出栈都是开头元素。底层实现和arraylist类似,都是动态数组,默认初始为16
4、Map
Map和set关系十分密切,实际上底层实现是先实现的map,然后包装一个所有value值都为null的map作为set
1)hashmap和hashtable
区别在于
1 hashtable是个古老的类,是线程安全的。而hashmap是线程不安全的
2 hashtable key和value都不允许放null值,而hashmap都允许
判断key hashcode和equals方法都相等时
判断value只需equals相等即可。
2)Linkedhashmap
和linkedhashset类似,通过链表的形式实现插入和迭代顺序的一致。
3)Properties类
是hashtable的子类,可以操作属性文件,比如ini格式的文件。可以把map对象和属性文件关联起来,既可以读取到map中,也可以将map 对象存到属性文件中。
4)TreeMap
和Set一样,Map中也有一个可以使得key-value对有序的TreeMap,且底层都是红黑树。
5)WeakHashMap
HashMap作用类似,但是里面都是弱引用
6)IdentityHashMap
判断key值是否相等时,必须要求key1==key2。而hashmap只需要hashcode相同,且equals返回true即可。
7)enumMap
和EnumSet类似,key不可存null,但value可以
8)性能分析
Hashmap快于hashtable,treemap由于维护红黑树,慢于以上两者。
Linkedhashmap慢于hashmap,enummap最快
9)Hashmap和hashset的底层
都是根据hashcode分配存储位置。
负载极限通常为0.75,即75%的位置都有元素时,会自动扩容
5、工具类collections类
1)同步
除了vector和hashtable以外,其他大部分都是线程不安全的。可以通过Collections.synchronizedXXX(new xxx())返回一个线程安全的
2)通过emptyXXX,singleton,unmodifiableMap可以返回不变类型的集合
3)通过Map,Set等类型的of方法,可以一次性创建包含多个元素的不变类型集合。