Java 基础 - 集合
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础 - 集合相关的知识,希望对你有一定的参考价值。
Collection
Collection 集合
在 java.util 包中, 其中 Collection
包含:
- List: 必须按特定的顺序容纳元素
- Set: 不可包含任何重复的元素
注意: Map
不在 Collection
集合中.
Collection
的主要方法
Boolean add(Object)
: 如果没添加, 则返回false
(Set
常用)Boolean addAll(Collection)
void clear()
: 清除所有Boolean contains(Object)
: 包含(通过比较equals
)则返回true
Boolean containsAll(Collection)
: 如果包含所有, 则返回true
Boolean isEmpty()
: 没有元素返回true
Iterator iterator()
: 返回迭代器,Collection
唯一的迭代方法Boolean remove(Object)
:true
代表有删除动作Boolean removeAll(Collection)
:true
代表有删除动作Boolean retainAll(Collection)
: 取交集, 有变动返回true
int size()
Object[] toArray()
: 返回一个数组Object[] toArray(Object[] a)
1.8新特性
Spliterator<E> spliterator()
Stream<E> stream()
Stream<E> parallelStream()
List
List
接口 继承自 Collection
接口, 它保证元素保存的顺序. 实现类主要有:
ArrayList
LinkedList
ArrayList
特点:
- 用于替换
Vector
- 数组实现
- 提供随机访问
- 查询快O(1), 插入删除慢
扩容:
- 初始值: 0
- 第一次增长: `minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
- 之后是每次 3/2 * oldCapacity + 1:
oldCapacity + (oldCapacity >> 1) + 1
LinkedList
特点:
- 双向链表实现
- 插入删除快
- 随机查找慢, 时间复杂度为O(n)
Set
Set
接口 继承自 Collection
接口, 它保证容器内元素唯一性, 不保证顺序. Set
中添加的对象, 必须重写了 equals()
方法(否则只是比较地址), 实现类有:
HashSet
TreeSet
HashSet
特点:
- 需要
hashcode
- 不保证顺序
- 用
HashMap
实现, 每次add
操作会调用map.put(ele, 预定义假对象);
TreeSet
特点:
- 保证顺序
TreeMap
实现, 每次add
操作会调用map.put(ele, 预定义假对象);
Map
用于存储 "键值对".包含:
- HashMap
- TreeMap
HashMap
特点:
- 用于代替
Hashtable
- 需要重写
hashCode()
和equals()
- 不保证顺序
put()
和get()
为常数时间
扩容:
- 初始值: 16, 负载因子为0.75, 初始阀值为 16*0.75
- 每次扩容, Capacity 加倍
与Hashtable
区别:
- 非线程安全, 要外部(调用者)保证线程安全
- 允许存放
<null, null>
影响HashMap
性能的参数:
初始大小和负载因子, 当(键值对数 > 总槽数 * 负载因子), 就会进行 rehash()
.
如何有效地减少rehash
操作, 以提高HashMap
性能? 1. 在设置初始大小的时候, 要考虑实际要存储多少元素, 以及增长因子(什么时候扩容), 这样的话, 就可以减少 rehash 的次数. 2. 当有特别多元素要存储的时候, 初始值要考虑设置的大一点. 这比每次扩容改变大小效率高很多.
TreeMap
特点: 1. 在 红-黑 树的基础上实现. 2. key 不能为 null, 和 HashMap
不同 3. 有 subMap()
方法, 可以返回树的一部分. 4. put()
和 get()
时间复杂度为 log(N) 5. 需要重写 equals()
6. 查询比 HashMap
快
TreeMap
是怎样排序的?
- 构造函数传入一个
Comparator
接口的实现 - 存储的
Object
实现了Comparable
接口
__Comparator
和 Comparable
有什么区别? Comparator
是外部比较器, 其比较方法compare(T o1, T o2)
有两个参数Comparable
是内部比较器, 起比较方法compareTo(T o)
只有一个参数
常用方法
排序和搜索
Array 排序
- 调用
Arrays.sort(a, new Comparator(){...})
- 假如 Object 实现了
Comparable
可以调用Arrays.sort(a)
Array 搜索
- 先 sort
- 然后调用
Arrays.binarySearch()
List 排序
- JDK 1.8 之前
- 先转化成数组:
Object[] a = list.toArray()
- 调用
Arrays.sort(a, new Comparator(){...})
, 假如 Object 实现了Comparable
可以调用Arrays.sort(a)
- 先转化成数组:
- JDK 1.8 之后, 可调用
void sort(Comparator c)
方法 - 调用
Collections.sort(List l)
方法
List 搜索
Collections.binarySearch(List, Object)
Set
- 转化成数组排序
- 先转化成数组:
Object[] a = list.toArray()
- 调用
Arrays.sort(a, new Comparator(){...})
, 假如 Object 实现了Comparable
可以调用Arrays.sort(a)
- 先转化成数组:
- 将
HashSet
转化成TreeSet
Map
- 将
HashMap
转化成TreeMap
其他实用方法
Collections
enumeration(Collection)
max(Collection)
min(Collection)
max(Collection, Comparator)
min(Collection, Comparator)
nCopies(int n, Object o)
: 返回一个不可边的List, 列表内的元素都指向 ounmodifiedbleCollection(Collection)
: 返回一个不可边的 CollectionsynchronizedList(List)
synchronizedSet(Set)
synchronizedMap(Map)
Enumeration和Iterator接口的区别?
Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,也满足了基础的需要。但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。
迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。
其他容器
Array
优点: 可以容纳基本数据类型 缺点: 提前分配空间
Vector, Stack, Hashtable
Vector
特点:
- 实现了
List
接口 - 线程安全, 方法都由
synchronized
标识, 有显著的性能开销 - 内部用数组实现
扩容:
- 初始值: 10 (默认构造函数)
- 每次扩容: old + (capacityIncrement==0 ? 0 : oldCapacity) + 1
Stack
特点:
- 继承自
Vector
- 先入后出(LIFO)
扩容, 同 Vector
Hashtable
特点:
- 实现了
Map
接口 - 存储
key-value
对 - 用内部类
Entry<K,V>
(实现Map.Entry<K,V>
接口) 数组 + 外部拉链法 - 线程安全, 通过为方法上加
synchronized
保证
扩容:
- 初始值: 11 (默认构造函数), 负载因子: 0.75
- 扩容条件: 每次
rehash()
都会扩容 rehash
条件:count >= threshold
,threshold
值为: 当前大小 * 负载因子- 每次扩容:
newCapacity = (oldCapacity << 1) + 1
- 最大不超过
MAX_ARRAY_SIZE
(Integer.MAX_VALUE - 8
最大值-8)
默认的 hashcode
是多少?
hashcode
默认值是由 Object
的hashcode
生成的, 值是这个对象的地址.
为什么要存到 HashMap/HashList/Hashtable 中的对象要重写 equals
和 hashcode
?
-
hashcode
默认值是对象的地址, 假如一个对象在Hashtable
中, 拿另外一个相等的对象查找, 会无法在Hashtable
中检索到, 因为两个对象地址不同, 所以检索到的 enties[index] 不同. -
之所以要重写
equals
, 是因为虽然通过hashcode
可以找到正确的entries[index]
, 但是在链表中找相等元素, 是比较equals
方法.
以上是关于Java 基础 - 集合的主要内容,如果未能解决你的问题,请参考以下文章