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
12Collections.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
7Set<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 协议 ,转载请注明出处!