《疯狂java讲义》读书笔记(四):Java集合

《疯狂java讲义》读书笔记(四):Java集合

图源网络,博客地址是https://www.cnblogs.com/jing99/p/7057245.html

在这里插入图片描述
在这里插入图片描述
集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象,而集合只能保存对象。

1.Collection和Iterator接口

​ Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用操作List和Queue集合。刚刚不是说集合里只能保存对象嘛,但是实际上我们操作的时候会发现下面的语句第三行居然也OK,原因是虽然集合里不能放基本类型的值,但是Java支持自动装箱。

Collection c=new ArrayList();
c.add("王二小");
c.add(6);

​ Iterable接口是Collection接口的父接口,因此Collection集合也可以直接调用Iterable接口中的forEach(Consumer action)方法,当程序调用该方法去遍历集合元素的时候,程序会依次将集合元素传给Consumeer的accept(T t)方法,正因为Consumer是函数式接口,因此可以使用Lambda去遍历集合元素。

​ 除了用lambda表达式去遍历集合元素之外,还可以用Java8增强的Iterator遍历集合元素。当使用Iterator对集合元素进行迭代的时候,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集合元素本身没有什么影响。也就是说使用Iterator迭代访问Collection集合元素时,Collection集合里的元素不会被改变,只有通过Iterator的remove()方法删除上一次next()方法返回的集合元素才可以。

​ Iterator接口中定义了下面4个方法:

boolean hasNext():如果被迭代的集合元素还没有被遍历完,则返回true
Object next():返回集合里的下一个元素,注意是Object类型,所以记得强制类型转换
void remove():删除集合里上一次next返回的元素
void forEachRemaining(Consumer action):可以用lambda表达式遍历集合元素

​ 还有要注意,别在Iterator迭代Collection集合的过程中修改集合,否则异常。

​ 除此之外,还可以用foreach循环遍历集合元素,不过foreach循环中的迭代变量也不是集合元素本身,只是将元素的值赋给迭代变量了,因此foreach循环中修改迭代变量的值也没啥实际意义,用foreach循环迭代的时候,集合也不能被改变,否则将引发异常。

2.Set集合

​ Set不允许包含重复元素。这里主要记录下HashSet、TreeSet和EnumSet三个实现类。

2.1HashSet类

​ 当向HashSet集合中存入一个元素的时候,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode(值,然后根据hashCode()值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法比较返回true,但他们的hashCode()方法返回值不相等,它们就会存储在不同的位置,依然可以添加成功,这样就和Set集合的规则冲突了。如果要是hashCode()方法返回的哈希值相同,但是equals()方法返回的是false的话,那么就会出现HashSet试图把它们保存在同一个位置,实际上就会在这个位置使用链式结构去保存多个对象,访问集合元素的时候使用哈希值来定位的,如果两个以上的元素具有相同的哈希值,那么性能就会下降。HashSet判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()返回值也相等。

​ 如果要重写HashCode(),那么应该遵循一些原则:比如说在程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值;当两个对象通过equals()方法比较返回true时,这两个对象的哈希值也该相等。

扫描二维码关注公众号,回复: 8736614 查看本文章

​ 总结一下HashSet的特点:

  • 不能保证元素的排列顺序,顺序可能和添加的顺序不同,也可能发生变化
  • HashSet不是同步的,多线程访问的时候得通过代码保证同步
  • 集合元素值可以null
2.2LinkedHashSet

​ LinkedHashSet是HashSet的子类,虽然也是用哈希值来决定元素的储存位置,但是它同时使用链表维护元素的次序。遍历的时候,会按照元素的添加顺序来访问集合里的元素。

2.3TreeSet

​ TreeSet使用红黑树的数据结构存储集合元素,支持自然排序和定制排序两种方法。自然排序就是用compareTo(Object obj)【Comparable接口中的方法】方法比较元素大小按照升序排列。如果想把一个对象添加到TreeSet时,则该对象的类就必须实现Comparable接口,否则就会抛异常。

​ 像BigDecimal、BigInteger、Character、Boolean、String、Date、Time都实现了Comparable接口。

​ 向TreeSet集合中添加元素的时候,第一个元素不需要实现Comparable接口,但是往后的所有元素都必须实现。不过向TreeSet中添加的应该是同一个类的对象!TreeSet通过compareTo(Object obj)判断两个对象相等。

2.4EnumSet

​ EnumSet集合元素时有序的,里面所有元素都必须是指定枚举类型的枚举值,EnumSet以枚举值在Enum类内定义的顺序来决定集合元素的顺序。不允许插入null元素,创建实例的话只能运用类方法来创建。类方法有很多,可以查阅API文档,如果用EnumSet.copyOf(Collection c)的话,要保证集合Collection里的元素都是同一个枚举类的枚举值。

3.List集合

​ List判断两个对象相等的标准是equals()方法是true。

3.1ArrayList和Vector

​ 动态的、允许再分配的Object[] 数组,使用initialCapacity参数来设置该数组的长度,当向ArrayList或者Vector中添加元素超出了该数组的长度时,initialCapacity会自动增加。ArrayList是线程不安全的,但是Vector是安全的,就算这样也不推荐使用Vector。Vector还有个Stack子类,不过使用栈的话推荐ArrayDeque了,因为挺古老的Stack。

3.2总结下List

​ 如果需要遍历List集合元素,对于ArrayList和Vector,应该使用get来遍历,如果是LinkedList,迭代器不错。要是经常插入、删除,可以考虑LinkedList。要是多线程同时访问的话,用Collections包装成线程安全的集合,最后面有说~

4.Queue集合

​ Queue有个Deque接口,代表着双端队列,Deque的实现类可以当队列使用也可以当成栈,Deque有ArrayDeque和LinkedList实现类。

​ PriorityQueue保证元素是按照大小重新排列的,如果peek()取出来的话,取出来的是最小的元素。

5.Map集合

5.1HashMap和HashTable

​ HashTable是线程安全的Map实现,但是HashMap不是,所以HashMap性能稍微高一点。HashTable不允许使用null作为key和value,但是HashMap可以。二者都不能保证key-val对的顺序,判断key相等的方法也是通过equals()方法比较返回true,哈希值相等。

5.2LinkedHashMap

​ 迭代顺序和键值对插入的顺序是一致的。

5.3使用Properties读写属性文件

​ 没想到Properties类是HashTable的子类。这个经常用,不多说了。

6.操作集合的工具类:Collections

​ 主要说下同步控制。直接将新创建的集合对象给Collections.synchronizedXxx()方法即可。

//创建了三个线程安全的集合对象。
Collection c=Collections.synchronizedCollection(new ArrayList());
List list=Collections.synchronizedCollection(new ArrayList());
Map m=Collections.synchronizedCollection(new HashMap());

发布了58 篇原创文章 · 获赞 5 · 访问量 6273

猜你喜欢

转载自blog.csdn.net/weixin_40992982/article/details/103980425