[笔记] 疯狂JAVA讲义(第3版)第8章 Java集合(一):https://developer.aliyun.com/article/1537901
8.4.2 ArrayList和Vector实现类
List的两个实现类。ArrayList和Vector都是基于数组实现的List类,封装了一个动态、可再分配的Object[] 数组。
允许使用initialCapacity参数设置数组长度,当元素超出该长度时,initalCapacity会自动增加。
通常无需关系initalCapacity,但如果要添加大量元素时,可以使用ensureCapacity(int minCapacity)一次性增加(到)initalCapacity。可以减少分配次数,提高性能。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46jLwn8w-1588248416674)(media/image6.png)]{width=“7.544671916010499in” height=“1.2098359580052493in”}
ArrayList和Vector用法上几乎完全相同,但Vector是一个古老的集合,里面有一些方法名很长的方法。
除此之外,ArrayList是线程不安全的。
Vector还提供一个Stack子类,模拟栈。由于Vector太古老了,不推荐使用Vector类。
8.4.3 固定长度的List
Arrays.asList(Object… a),将一个数组或指个数的对象转换成一个List集合,该集合是Arrays的内部类ArrayList的实例。
Arrays.ArrayList是一个固定长度的List集合,程序只能遍历集合元素,不可增减。
package ch8; import java.util.Arrays; import java.util.List; public class FixedSizeList { public static void main(String[] args) { List fixedList = Arrays.asList(“fk java”,“java EE”); System.out.println(fixedList.getClass()); fixedList.forEach(System.out::println); } }
8.5 Queue集合
Queue用于模拟队列。队列是先进先出(FIFO)的容器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxVKZt0b-1588248416675)(media/image7.png)]{width=“7.628687664041995in” height=“1.873565179352581in”}
8.5.1 PriorityQueue
Queue的比较标准的实现类。但PriorityQueue保存元素的顺序是按照元素的大小排序的。
因此,并不是按照FIFO原则。
package ch8; import java.util.PriorityQueue; public class PriorityQueueTest { public static void main(String[] args) { PriorityQueue pq = new PriorityQueue(); pq.offer(6); pq.offer(-3); pq.offer(20); pq.offer(18);
System.out.println(pq); //输出[-3,6,20,18],受到toString()的影响,实际上调用poll()是按从小到大排序的。
System.out.println(pq.poll()); System.out.println(pq.poll()); System.out.println(pq.poll()); System.out.println(pq.poll()); } }
PriorityQueue的排序方式和TreeSet基本一致。
8.5.2 Deque接口和ArrayDeque实现类
Deque是一个双端序列。允许从两端操作数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwrZi1Er-1588248416675)(media/image8.png)]{width=“7.922744969378828in” height=“4.923360673665792in”}
Deque接口提供了一个典型的实现类:ArrayDeque,可以用来实现Stack和Queue。
package ch8; import java.util.ArrayDeque; public class ArrayDequeueStack { public static void main(String[] args) { ArrayDeque stack = new ArrayDeque(); stack.push(“java”); stack.push(“javase”); stack.push(“Android”); System.out.println(stack); System.out.println(stack.peek()); System.out.println(stack); System.out.println(stack.pop()); System.out.println(stack); } } package ch8; import java.util.ArrayDeque; public class ArrayDequeQueue { public static void main(String[] args) { ArrayDeque queue = new ArrayDeque(); queue.offer(“java”); queue.offer(“javaee”); queue.offer(“Android”); System.out.println(queue); System.out.println(queue.peek()); System.out.println(queue); System.out.println(queue.poll()); System.out.println(queue); } }
8.5.3 LinkedList实现类
List的实现类,此外,LinkedList还实现了Deque接口。
package ch8; import java.util.LinkedList; public class LinkedListTest { public static void main(String[] args) { LinkedList books = new LinkedList(); books.offer(“java”); books.push(“javaee”); books.offerFirst(“Android”); for(int i = 0 ; i < books.size() ; i++) { System.out.println(books.get(i)); } System.out.println(books.peekFirst()); System.out.println(books.peekLast()); System.out.println(books.pop()); System.out.println(books); System.out.println(books.pollLast()); System.out.println(books); } }
8.5.4 各种线性表的性能分析
List:线性表接口
ArrayList、LinkedList 两种实现
Queue:队列
Deque:双端队列
一般来说,ArrayList随机访问性能好,LinkedList插入删除时性能好。总体来说,ArrayList性能更好。
List使用使用建议:
遍历:对于ArrayList,使用随机访问 get()方法来遍历;而LinkedList,使用迭代器(Iterator)遍历
线程安全:多线程时,考虑使用Collection将集合包装成线程安全的集合。
8.6 Java 8 增强的Map集合
Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组保存Key,另一组保存Value。
key和value都可以是任何类型的数据,key不能重复。
key -value一一对应。
@key集存储方式和Set存储形式完全相同。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PWWffom-1588248416677)(media/image9.png)]{width=“9.317416885389326in” height=“6.998565179352581in”}
package ch8; import java.util.HashMap; import java.util.Map; public class MapTest { public static void main(String[] args) { Map map = new HashMap(); //放入key-value对,value可以重复,如果放入重复的key,新的value值会覆盖原来的value map.put(“疯狂Java讲义”,109); map.put(“疯狂IOS讲义”,10); System.out.println(map); //判断是否包含指定key System.out.println(“包含值 疯狂IOS讲义的key:”+map.containsKey(“疯狂IOS讲义”)); //判断是否包含指定value System.out.println(“包含值为99的value:”+map.containsValue(10)); //获取key集合,通过遍历key遍历key-value对 for(Object key : map.keySet()) { System.out.println(key+"–>"+map.get(key)); } map.remove(“疯狂IOS讲义”);//根据key来删除key-value对 System.out.println(map); } }
8.6.1 java8为Map新增的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ngbFHAIz-1588248416679)(media/image10.png)]{width=“8.065573053368329in” height=“7.191802274715661in”}
package ch8; import java.util.HashMap; import java.util.Map; public class MapTest2 { public static void main(String[] args) { Map map = new HashMap(); //放入key-value对 map.put(“疯狂java”,109); map.put(“疯狂IOS”, 99); map.put(“疯狂Ajex”, 79); map.replace(“疯狂XML”, 66); //替换key为"疯狂XML"的value。但由于原map没有此key,所以不会替换。也不会新加键值对 System.out.println(map); //覆盖原value, 变成oldV + 10 map.merge(“疯狂IOS”, 10, (oldV,param)->(Integer)oldV + (Integer)param); System.out.println(map); //当key为java对应的value为null或不存在时,使用计算的结果作为新value map.computeIfAbsent(“java”, (key)->((String)key).length()); System.out.println(map); //key对应value存在时,计算新value map.computeIfPresent(“java”, (key,value)->(Integer)value*(Integer)value); System.out.println(map); } }
8.6.2 java 8改进的HashMap和Hashtable实现类
Hashtable是一个古老的Map实现类,不推荐使用。
为了能够在HashMap中存储对象,作为key的对象必须实现hashCode()和equals()方法。
8.6.3 LinkedMap实现类
使用双向链表维护key的次序。
package ch8; import java.util.LinkedHashMap; public class LinkedHashMapTest { public static void main(String[] args) { LinkedHashMap scores = new LinkedHashMap(); scores.put(“语文”,90); scores.put(“数学”,92); scores.put(“英语”,80); scores.forEach((key,value)->System.out.println(key+"–>"+value)); } }
8.6.4 使用Properties读取属性文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qyuatnOx-1588248416681)(media/image11.png)]{width=“8.073975284339458in” height=“4.318442694663167in”}
package ch8; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Properties; public class PropertiesTest { public static void main(String[] args)throws Exception { Properties props = new Properties(); //添加属性 props.setProperty(“username”, “yuke”); props.setProperty(“password”, “123456”); //保存至a.ini文件 props.store(new FileOutputStream(“a.ini”),“comment line”); Properties p2 = new Properties(); p2.setProperty(“gender”, “male”); //将a.ini中key-value追加到p2中 p2.load(new FileInputStream(“a.ini”)); System.out.println(p2); } }
8.6.5 SortedMap接口和TreeMap实现类。
TreeMap存储key-value时,根据key进行排序,保证有序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7B5lp8Qi-1588248416681)(media/image12.png)]{width=“8.157991032370953in” height=“7.8471303587051615in”}
8.6.6 WeakHashMap实现类
类似HashMap,但WeakHashMap只保留对实际对象的弱引用,对象在垃圾回收时可能会被回收。
8.6.7 IdentityHashMap实现类
类似HashMap,但处理相等的key时,仅在key1==key2严格相等时,才认为相等。而HashMap只判断equals()和hashCode()方法。
8.6.8 EnumMap实现类
创建EnumMap时必须指定一个枚举类。
8.6.9 各Map实现类的性能分析
对于一般场景,应该考虑使用HashMap.
如果需要排序,则可以考虑TreeMap。
8.7 HashSet和HashMap的性能选项
HashSet类采用hash算法决定元素存储位置,并通过hash算法来控制集合的大小;
hash表里可以存储元素的位置称为"桶(bucket)",通常情况下,单个"桶"存放一个元素,此时有最好的性能。
hash算法根据hashCode值计算出"桶"的位置,接着从"桶"中取出元素。
但发生hash冲突时,单个桶会存储多个元素,这些元素以链表形式存储,必须按顺序搜索。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XLY8aPY-1588248416682)(media/image13.png)]{width=“3.1758191163604548in” height=“1.6887292213473315in”}
HashSet、HashMap的hash表中都包含如下属性:
容量(capacity):桶数量
初始化容量(initial capacity):
尺寸(size):当前数量
负载因子(load factor):负载因子等于size/capacity,负载因子=0,代表空,负载因子=0.5,代表半满。
负载极限:0~1,当负载因子达到负载极限时,hash表会自动成倍增加容量。默认值0.75.
8.8 操作集合类的工具类:Collections
Collections类提供对集合元素排序、查询、修改等操作。
8.8.1 排序操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x0VXM5RJ-1588248416683)(media/image14.png)]{width=“7.586679790026246in” height=“2.1424179790026248in”}
package ch8; import java.util.ArrayList; import java.util.Collections; public class SortTest { public static void main(String[] args) { ArrayList nums = new ArrayList(); nums.add(2); nums.add(-5); nums.add(3); nums.add(0); System.out.println(nums); Collections.reverse(nums);//翻转 System.out.println(nums); Collections.sort(nums);//排序 System.out.println(nums); Collections.shuffle(nums);//随机顺序 System.out.println(nums); } }
8.8.2 查找、替换操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gs5PfYPQ-1588248416684)(media/image15.png)]{width=“7.947950568678915in” height=“3.94876968503937in”}
package ch8; import java.util.ArrayList; import java.util.Collections; public class SearchTest { public static void main(String[] args) { ArrayList nums = new ArrayList(); nums.add(2); nums.add(-5); nums.add(3); nums.add(0); System.out.println(nums); System.out.println(Collections.max(nums)); System.out.println(Collections.min(nums)); Collections.replaceAll(nums, 0, 1);//替换 System.out.println(nums); System.out.println(Collections.frequency(nums, -5)); Collections.sort(nums);//排序 System.out.println(nums); System.out.println(Collections.binarySearch(nums, 3));//二分查找,要求是排序好的 } }
8.8.3 同步控制
Collections类提供多个synchronizedXxx()方法,可以将指定集合包装成线程同步的集合。
如:
List list = Collections.synchronizedList(new ArrayList());
8.8.4 设置不可变集合
Collections类提供三类方法来返回一个不可变的集合:
emptyXxx(): 返回一个不可变的Xxx
singletonXxx():返回一个只包含指定对象的xx
unmodifiableXxx():返回指定对象的不可变视图。
package ch8; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; public class UnmodifiableTest { public static void main(String[] args) { List unmodifiableList = Collections.emptyList(); Set unmodifiableSet = Collections.singleton(“疯狂Java讲义”); Map scores = new HashMap(); scores.put(“语文”,100); scores.put(“数学”,99); Map unmodifiableMap = Collections.unmodifiableMap(scores); } }
8.9 繁琐的接口:Enumeration 很古老,建议略过,当然我只是建议
//小结,Java集合,内容很多,很难记住每个类的细节,看完书后要做一下精简版的总结。