第八章 java集合
8.1 java集合
集合用来保存数量不确定的数据,以及保存具有映射关系的数据。也被称为容器类。集合类都位于java.util包下。集合只能保存对象。
java集合由 collection和map两个接口派生。
8.2 Collection和Iterator接口
添加对象,删除对象,清空容器,判断容器是否为空
当使用System.out.println()时会输出[ ele1,ele2...]这是因为所有的Collection都重写了toString的方法。如果想一次访问集合中的每个元素,需要使用下面的方法遍历元素。
8.2.1 使用Lambda表达式遍历集合
Collection可以直接调用foreach(Consumer action)方法,因为Consumer是函数式接口,所以可以用Lambda表达式
8.2.2 使用java8增强的Iterator遍历集合元素
Iterator也是java集合框架的成员,但是主要用于遍历Collection中的元素,Iterator对象也被称为迭代器。
Iterator it=books.iterator();Iterator必须依赖Collection对象
it.hasNext();
it.next();
it.remove();
iterator对集合进行迭代时,只是把集合元素的值传递给了迭代变量,所以修改迭代变量的值不会对集合元素本身有任何影响。
如果在iterator迭代collection集合过程中修改collection集合。程序会在运行时发生异常。
8.2.3 使用Lambda表达式遍历Iterator
forEachRemaining(Consumer action)
8.2.4 使用foreach循环遍历集合元素
for(Object obj:book)
8.2.5 使用java8新增的predicate操作集合
removeIf(predicate filter)把满足predicate的方法留下来
8.2.6使用java新增的Stream操作集合
Stream是一个通用的流接口,
独立使用Stream的步骤:
1.调用Builder()
2.add()
3 调用build()
4.使用聚集方法,大部分聚集方法,每个只能执行一次
Stream提供了大量的方法进行聚类操作
分为:中间方法 末端方法
有状态的方法 短路方法
8.3 Set集合
实际上Set就是Collection ,只是Set不允许包含重复元素。
8.3.1 HashSet类
HashSet是Set接口的典型实现,HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能
特点:
- 不能保证顺序
- 不是同步的
- 集合元素值可以是null
HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也是相等的。
如果多个元素的 hashCode值相同,但是它们通过equals返回false,则需要在一个桶里面保存多个元素,导致性能的下降。
重写hashCode()方法的基本规则 - 在程序运行过程中,同一个对象多次调用hashCode()返回值相同
- 当两个对象通过equals()方法返回true时,这两个对象的hashCode()方法返回值相同
- 对象用作equals()方法比较标准的实例变量,都应该用于计算hashcode值
注意⚠:当程序吧对象添加到hashSet后,尽量不要更改集合元素中参与计算hashCode() equals()的实例变量,否则将导致无法正确操作这些元素。
8.3.2 LinkedHashSet
LinkedHashSet是HashSet的子类,但是总是按照添加的顺序保存对象。但是仍然不能有重复。
8.3.3 TreeSet类
TreeSet类是SortedSet接口的实现类。TreeSet可以确保集合元素处于排序状态。
1.自然排序
调用集合元素的compareTo(Object obj)来比较元素之间的大小关系,然后把集合元素按升序排列。
注意⚠:
试图把一个对象加入TreeSet时,该对象必须实现Comparatable接口,否则程序将抛出异常。
总结一句话:TreeSet如果想正常运行,必须只能添加同一种类型的对象。
TreeSet集合判断两个对象是否相等的唯一标准是:两个对象通过compareTo()方法比较是否返回0。
注意⚠:不要修改TreeSet集合元素的关键实例变量。
2.定制排序
实现定制排序,在创建TreeSet对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。
EnumSet类
EnumSet是专门为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,元素是有序的,EnumSet以枚举值在Enum类内定义顺序来决定集合的顺序,
EnumSet 集合不允许加入null, 且必须用类方法创建。
当试图复制一个Collection集合里的元素来创建EnumSet集合时,必须保证Collection集合里面的所有元素都是同一个枚举类的枚举值。
8.3.5 各Set实现类的性能分析
HashSet性能总是比TreeSet好,
只有当需要一个保持排序的Set时,在应该使用TreeSet'
LinkHashSet遍历起来更加方便,普通的操作不如HashSet
EnumSet性能最好,但是有局限
这三个都是线程不安全的。必须手动同步。
8.4 List集合
List集合代表一个元素有序,可重复的集合。集合中每个元素都有其对应的顺序索引。
8.4.1 java8改进的List接口和ListIterator接口
List集合增加了一些根据索引来操作集合元素的方法。
List判断两个对象相等只要通过equals()方法比较返回true.
set(int index,Object element)方法不会改变List集合的长度。
ListIterator方法来遍历List元素。它增加了向前迭代的功能。hasPrevious() lit.previous()
8.4.2 ArrayList和vector实现类
不要用vector stack
用ArrayList ArrayDeque
8.4.3 固定长度的List
有一个操作数组的工具类Arrays,有一个asList()方法,可以把一个数组或者指定个数的对象转换成list集合,这个集合时Array的内部类ArrayList的实例,时固定长度的List集合。
8.5 Queue集合
Queen用于模拟队列这种数据结构,队列通常是“先进先出”的容器。
8.5.1 PriorityQueen实现类
PriorityQueen是一个比较标准队列实现类,因为保存队列元素的顺序并不是按照加入的顺序,而是按照队列元素的大小重新排列。
注意⚠:不允许插入null元素
8.5.2 Deque接口与ArrayDeque实现类
Deque接口是Queen 接口的子接口,代表一个双短队列
Deque接口提供了一个典型的实现类:ArrayDeque。基于数组实现的双端队列。既可以当栈,也可以当队列。当栈的话,就用push peek pop
当队列的话,就用offer peek poll.
8.5.3 LinkedList实现类
既可以当栈,也可以当队列
8.5.4 各种线性表的性能对比
- 如果需要遍历集合元素,ArrayList更好,使用随机访问方法(get)来遍历
- 如果经常执行插入删除,LinkedList更好
- 如果多个线程同时访问List 集合中元素,考虑使用Collections将集合包装成线程安全
8.6 java8增强的Map集合
Map又叫字典,或者关联数组。
8.6.2 java8改进的HashMap和Hashtable实现类
判断两个key相等的条件:两个key通过equals()比较返回true,并且hatched相等。
判断两个value相等的雕件:通过equals返回true
注意⚠:尽量不要使用可变对象作为hashmap的key,如果做了,也尽量不要改变。
8.6.3 LinkedHashMap实现类
使用双向链表维护key-value的次序,迭代顺序与key-value对的插入顺序一致
8.6.4 使用Properties读写属性文件
可以把map对象和属性文件联系起来,从而把Map 对象中的key-value对写入属性文件,也可以把文件中的key-value加载到map中,key和value都是字符串类型。
8.6.5 SortedMap接口和TreeMap实现类
8.6.6 WeakHashMap实现类
8.6.7 IdentityHashMap
当且仅当两个key严格相等(==),才认为两个key相等。
8.6.8 EnumMap实现类
8.6.9 性能分析
HashMap最常用
8.7 HashSet和HashMap的性能选项
负载极限