Java基础(五)—— 集合
本文最后更新于:2022年7月21日 上午
概览:Java集合
内容不完整,后续补充。
集合框架

- 位于java.util包中。
- Collections类中提供了对集合进行排序、遍历等多种算法
要素
- Collection接口存储一组不唯一、无序的对象、
- List接口存储一组不唯一、有序的对象。
- Set接口存储一组唯一、无序的对象。
- Map接口存储一组键值对象,提供key到value的映射。
- ArrayList实现了长度可变的数组,在内存中分配连续的空间,遍历元素和随机访问元素的效率比较高。
- LinkedList采用了链表存储方式,插入、删除元素是效率比较高。
- HashSet采用了哈希算法实现的- Set,- HashSet底层是采用了- HashMap实现的,因此查询效率较高,由于采用了hashcode算法直接确定元素的内存地址,增删效率比较高。
ArrayList
- Arraylist是可以动态增长和缩减的索引序列。
- 该类封装了一个动态再分配的Object[]数组,每一个类对象都有capacity的属性,当往集合中增加元素时,该属性值会自动增加。
- ArrayList的用法类似于- Vector,但是- Vector比较老,缺点很多,不建议使用。
- ArrayList是线程不安全的,当多个线程访问同一个- ArrayList集合时,需要手动保证集合的同步性。而- Vector则是线程安全的。
类中的属性
| 1 |  | 
方法:
| 方法 | 描述 | 
|---|---|
| boolean add(Object o) | 在列表的末尾顺序添加元素,起始索引位置从0开始。 | 
| void add(int index,Object o) | 在指定的索引位置添加元素,索引位置介于0和长度之间 | 
| int size() | 返回列表的元素个数 | 
| Object get(int index) | 返回指定索引位置处的元素,去除的元素是Object类型,需要强制类型转换 | 
| boolean contains(Object o) | 判断列表中是否存在指定元素 | 
| boolean remove(Object o) | 从列表中删除元素 | 
| Object remove(int index) | 从列表中删除指定位置元素 | 
boolean addAll(Collection c) //讲一个集合中的所有对象添加到此集合中。
void clear() //清空此集合中的所有对象。
boolean equals(Object o) //比较此集合是否与指定对象相等。
boolean isEmpty() //判断此集合是否为空。
Object[] toArray() //姜此集合转换成数组。
应用:
| 1 |  | 
| 1 |  | 
Guava Lists
- Collections.emptyList();可以返回一个空的list
| 1 |  | 
Guava Collections
- emptyList/emptySet/emptyMap:获取一个空的集合,但是不可写 
- singleton/songletonList:获取只有一个元素的Set/list,但是不可写 
- shuffle打乱一个list 
- sort排序,默认从小到大 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- Collections.sort(list,new Comparator<Integer> {
 @override
 public int compare(Integer o1,Integer o2){
 return o1 > o2 ? -1 : (o1 < o2 ? 1 : 0);
 }
 });
 // Guava的方法
 Collections.sort(list,Ordering.natural().reverse());//逆序排序
 // 不打乱原来的排序,生成一个新的排序
 List<Integer> relist = Ordering.natural().reverse().sortedCopy(list);
总结
- ArrayList可以存放null
- ArrayList本质上是一个数组,不过是可以自动扩展大小,关键方法在于grow()。
- ArrayList在数据查询方面比较快,而在插入删除方面则比较慢,因为连续的空间,需要移动大量的数据。
LinkedList
- LinkedList是一个可以在任意位置进行高效插入与删除的有序序列,基于双向链表实现。
- LinkedList是一个继承于- AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队 列进行操作。
- LinkedList实现 List 接口,能对它进行队列操作。
-  LinkedList实现Deque接口,即能将LinkedList当作双端队列使用。
- LinkedList实现了- Cloneable接口,即覆盖了函数- clone(),能克隆。
- LinkedList实现- java.io.Serializable接口,这意味着- LinkedList支持序列化,能通过序列化去传输。- LinkedList是非同步的。
特殊方法:
| 方法名 | 说明 | 
|---|---|
| void addFirst(Object o) | 在列表首部添加元素 | 
| void addLast(Object o) | 在列表的末尾添加元素 | 
| Object getFirst() | 获取列表第一个元素 | 
| Object getLast() | 获取列表最后一个元素 | 
| Object removeFirst() | 删除并返回列表第一个元素 | 
| Object removeLast() | 删除并返回列表最后一个元素 | 
总结
- 可以存储null
- 异步,非线程安全
- 双向链表实现,适用于频繁的插入和删除操作。
Vector & Stack
优先级队列 PriorityQueue
| 1 |  | 
Map
map有两个参数
- Capacity,默认16
- Load factor,默认0.75,即表示当当前的容量扩展到最大容量的75%时就会扩大容量一倍,然后重新对已有的内容进行哈希重排,保证o(1)的效率。
- 默认无序
- TreeMap是可以排序的
- Guava Maps.newHashMapWithExpectedSize(size)- 指定size之后,会自动计算出对应的初始容量,在达到一定数据量之前不会进行扩容。
 
- 线程不安全
- 线程安全的map:ConcurrentHashMap
Set
基于map来实现
- Map<E,object>
Guava
●Lists/Sets/ Maps
-提供工厂方法
- Lists.newArrayList(), 用于创建一个空ArrayList, 与使用原生JDK语法进行比较, 更加简洁,易懂:
- List<Map<Integer, List>> jdkArrayList = new ArrayList<Map<Integer, List >>(); 
 List<Map<Integer,List>> guavaArrayList = Lists .newArrayList(); 
- Lists. newArrayListWithCapacity(int), 用于创建一个ArrayList, 返回的容器容量和参数给出的大小一致
- Maps.newHashMapWithExpectedSize(int),用于创建一个HashMap, 返回的容器具有初始容量(不是元素个数),初始容量约为传入参数给出大小的4/3倍。
- asList/asSet/asMap系列方法,注意,这些方法返回的是视图,即原容器变更会影响这些方法返回的容器内容
集合上的常见操作
- Lists.reverse用于翻转
- Lists.transform 用于List变形
| 1 |  | 
- Lists.partition可以用于分割List 
- Sets.filter 过滤元素 - 1 
 2
 3
 4
 5
 6
 7- Set<Integer> intSet = Sets.newHashSet(1,2,3,4);
 Set<Integer> greaterTwoSet = Sets.filter(intSet, new Predicate<Integer>() {
 @Override
 public boolean apply(Integer integer) {
 return integer > 2;
 }
 });
- . Maps. filterKeys/ .filterValues/ . filterEntries,过滤某些关联关系 
- Maps. transformValues/ . transformEntries,变形成另一个Map 
- Maps. difference, 返回两个Map之间的差异 
- 关于Map的补充工厂方法 
- Maps. fromProperties,从Properties文件构造一 个Map, 该Map不可修改 
- Maps. uniquelndex(Iterable, Function), 根据Value构造一个Map, 例如,从数据库中读 
 取一批数据,数据的某- -有唯一索引的列建立Map
| 1 |  | 
新集合 MultiSet
- Set中所有元素互不相同。
- Multiset允许出现重复元素,并且元素之间没有顺序,除了TreeMultiset外。
计数操作
| 1 |  | 
MultiMap
- 可以建立1-> n的关系
- 原生的1对多的建立方式是,key对应一个set集合
Immutable
●ImmutableXXX
. ImmutableXXX
提供不可修改容器的功能,保证返回的容器不能被调用者修改,并且原容器的修改不会影响ImmutableXXX
对不可靠的客户代码库来说,它使用安全,可以在未受信任的类库中安全的使用这些对象
线程安全的: Immutable对象在多 线程下安全,没有竞态条件不需要支持可变性,可以尽量节省空间和时间的开销。所有的不可变集合实现都比可变集合更加有效的利用内存
可以被使用为一个常量,并且期望在未来也是保持不变的
- 不可变指的是不能修改引用的指向,不能add内容,是容器内的元素还是可以继续修改的。
- 返回的对象不是原容器的视图,而是原容器的一种拷贝。- 不是deep copy,所以还是容器出现问题
 
- 但是JDK提供的类似容器返回的是试图
BiMap
●BiMap
- JDK提供的Map只提供根据Key查找Value,无法通过Value查找Key
 .有些场景,需要根据Value查找Key, 例如:
 .根据城市Code查询城市名称,同时还需要根据名称查询Code
 .固定集合内单词的中英文互译
 . Guava提供BiMap,使得Key-Value均可以查询
- BiMap.get- -根据Key查询Value
- BiMap.inverse().get– 转换Key-Value顺序, 再通过get根据Value查询Key
 .需要注意的是,使用BiMap时,Key-Value必须都是唯一 的,即所有的Value也必须互不
 相同
RangeSet/ RangeMap
-用于存放区间(Range) 的容器,并提供诸如区间合并,区间分裂等功能
●AtomicLongMap
-能对Map中的Value进行原子的更新
-常用来进行统计,例如,监控系统可以使用AtomicLongMap记录各项监控数据等
-每一个Key都是一个监控的名称,Value都是监控值
- addAndGet()/ getAndAdd()- - - 增加然后获取值/获取完值之后增加
- incrementAndGet()/ decrementAndGet()/ getAndIncrement()/ getAndDecrement()
 . ++i/–i/i++/i–
- removeAllZeroes()- - - 去除所有为0的entry, 非原子,即此方法调用过程中,其他线程可能
 取到Map中的0值
- sum()- –累积值
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!