集合
结构
Collection
方法
- 主要实现的就是对集合的增删改查(CRUD)
调用名称 | 作用 |
---|---|
add (Object o) | 添加一个元素o,凡是Object的实例都可以添加 |
addAll (Collection c) | 添加多个元素 |
remove (int index) | 根据索引删除元素 |
remove (Object o) | 删除元素o |
removeAll (Collection c) | 删除多个元素 |
contains (Object o) | 查看元素o是否存在,存在返回true,否则false |
containsAll(Collection c) | 判断多个元素是否存在 |
size() | 获取集合内元素的个数 |
isEmpty() | 判断集合是否为空 |
clear() | 清空集合 |
遍历
利用Iterator
进行遍历
- 调用集合的
Iterator()
方法,返回获得一个Iterator
对象,遍历该对象,这个对象称为迭代器 - 获取方式:
Iterator iterator = list.iterator()
Iterator
仅用于遍历,本身不存放对象- 使用
while
遍历
while (iterator.hasNext()) {
Object next = iterator.next();
}
知识点:
IDEA可以使用itit快捷键;
hasNext():判断是否还有下一个元素
next():1、指针下移;2、返回元素;3、返回的是Object类型
- 使用
for each
遍历
for (Object obj : list) {
System.out.println(obj);
}
知识点:
for each的底层用的也是Iterator迭代器
for each也可以遍历数组
List
特点
- 有序,有索引
方法
调用名称 | 功能 |
---|---|
void add (int index,Object o) | 在指定位置添加元素o |
boolean addAll(int index,Collection c) | 在指定为添加多个元素c |
Object get(int index) | 获得指定位置的元素 |
Object remove(int index) | 删除指定位置的元素 |
Object set(int index,Object ele) | 将index位置的元素置为ele,相当于替换 |
int indexOf(Object obj) | 返回obj第一次在集合中出现的位置 |
int lastIndexOf(Object obj) | 返回obj最后一次在集合中出现的位置 |
List subList(int fromIndex,int toIndex) | 返回从fromIndex到toIndex位置的子集合 |
ArrayList
- 底层实现:可变数组
- 扩容策略
1、对于使用无参构造器
List list = new ArrayList();
初始容量为0,第一次扩容为10,往后每一次扩容前一容量的1.5倍
2、对于调用有参构造器
ArrayList list = new ArrayList(8);
初始容量为指定的容量,往后每次扩容为前一容量的1.5倍
- 线程不安全
LinkedList
- 底层实现:双向链表
- 维护的属性
1、LinkeList维护两个属性:first,last
first:指向首节点
last:指向尾节点
2、每个Node维护三个属性:prev,next,item
prev:指向前一个节点
next:指向后一个节点
item:存放数据
- 扩容策略,因为是链表,直接扩
- 线程不安全
Vector
- 底层实现:可变数组
- 扩容策略
1、对于使用无参数构造器
Vector vector = new Vector();
初始为0?,第一次扩容默认为10,往后每次扩容为前一容量的2倍
2、对于使用有参数构造器
Vector vector = new Vector(8);
初始容量为指定的大小,往后每一次扩容为前一容量的2倍
- 线程安全:使用的synchronized
Set
特点
- 无序的,没有索引
- 不允许存在重复的元素,可以包含null(也只能包含一个null)
- 输出的顺序与输入的顺序很可能是不一致的,但每次输出的顺序都是一致的
方法
HashSet
- 底层是
HashMap
,由 数组(table)+单链表+红黑树 实现,优点是存取效率很高 - 扩容策略
1、初始化默认 table 为null
2、添加第一个元素时,table 扩容为16
3、阈值设置为 0.75*(table的大小),当集合内元素个数到达阈值时,table就会扩容
问题:每次扩容的大小?只要元素个数到达阈值就一定会扩容吗?
- 添加元素策略
1、添加到Set内的元素是一个Node,包含value与next,实际上有(key,value,next),但是在set中,key代表值,value为空。
2、元素根据hash值找到位置后,判断该位置是否为null,若为null直接加入该Node
3、若不为null,则需要比较当前位置的数据,若相同则取消添加,若不相同,则以链表的形式,加在尾部
4、若table >= MIN_TREEIFY_CAPACITY(默认64)且 链表大小>= TREEIFY_THRESHOLD(默认8),则链表树化
5、如果 table 没有超过64,但某一节点链表超过8个,则先扩容table,扩容至64后,在将节点树化
- 判断元素是否相同,
hashCode()
与equals()
1、判断元素是否相同的条件
p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))
LinkedHashSet
- 底层维护是LinkedHashMap,维护一个 数组(table) + 双向链表,实际上就是HashSet底层的单链表多加了before和after
- 输出顺序与输入顺序相同
TreeSet
- 底层机制是
TreeMap
- 对集合内的元素能够进行排序
1、当调用默认的无参构造器时,可以进行自然排序
TreeSet treeSet = new TreeSet();
treeSet.add("jack");
treeSet.add("zom");
treeSet.add("bp");
treeSet.add("apple");
System.out.println(treeSet); // [apple, bp, jack, zom]
2、可以自主选择排序规则,例如:按照长度大小排序
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length()-((String) o2).length();
}
});
treeSet.add("jack");
treeSet.add("zom");
treeSet.add("bp");
treeSet.add("apple");
treeSet.add("abc"); // 用长度比,加不进去
System.out.println(treeSet); // [bp, zom, jack, apple]
- 根据比较器的规则,进行排序的底层局部代码,(二叉排序树?)
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else {
V oldValue = t.value;
if (replaceOld || oldValue == null) {
t.value = value;
}
return oldValue;
}
Map
特点
- 是一组具有映射关系的序列对
(key, value)
的集合,无序 - 一对
(key, value)
存放在一个Node(HashMap$Node)
中
HashMap$Node node = newNode(hash,key,value,null)
- key不可重复,value可以重复
Map map = new HashMap();
//加入元素
map.put("no1","张无忌");
map.put("no2","韩顺平");
map.put("no1","张三丰"); //当有相同的key时,新的替换掉旧的
- Map在底层维护一个
entrySet
集合,该集合存放的类型是Entry
1、底层维护一个entrySet的集合,其中Map.Entry是Map的内部接口,
transient Set<Map.Entry<K,V>> entrySet;
2、entrySet中,定义的类型是Map.Entry,但实际上存放是对HashMap$Node的引用,Node实现了Map.Entry接口
大概流程:HashMap$Node -> 向上转型为 Entry -> 将引用放入entrySet
Map map = new HashMap();
Set set = map.entrySet() // 得到一个entrySet集合
3、Entry类实际上是Map中的内部接口,Entry接口提供了两个重要方法:getKey() 于 getValue()
Set set = map.entrySet();
for (Object obj : set ) {
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + " - " + entry.getValue());
}
4、keySet()存放key的集合,values()存放value的集合,实际上里面存放的也是引用
Map map = new HashMap();
Set keys = map.keySet();
Collection values = map.values();
方法
调用名 | 功能 |
---|---|
put(Object key, Onject value) | 添加一对映射关系 |
remove(Object key) | 删除一对映射关系 |
get(Object key) | 根据key获取一个value |
size() | 获取集合中键值对的个数 |
isEmpty() | 判断的键值对的个数是否为0 |
containsKey(object key) | 判断key是否存在 |
clear() | 清除键值对 |
遍历
- 利用keySet()
Map map = new HashMap();
Set keyset = map.keySet();
1、for each
for (Object key : keyset) {
System.out.println(map.get(key));
}
2、迭代器
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
}
- 利用values()
Map map = new HashMap();
Collection values = map.values();
1、for each
2、迭代器
- 利用entrySet()
Map map = new HashMap();
Set set = map.entrySet();
1、 for each
for (Object o : set) {
Map.Entry entry = (Map.Entry) o;
System.out.println(entry.getValue());
}
2、迭代器
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()) {
Map.Entry next = (java.util.Map.Entry) iterator1.next();
System.out.println(next.getValue());
}
HashMap
特点
- 数据以
HashMap$Node
形式存储 - 以(key, value)键值对的方式存放数据
- Key可以为
null
,Value也可以为null
。注意:Key只能有一个null
,value可以包含多个null
- 线程不安全
底层机制
- 底层是由 数组 + 链表 + 红黑树 组成
扩容策略
- 加载因子 loadfactor 初始化为0.75
- 添加元素 ,利用hashCode()找到table表中的位置
若该位置为null:直接加入
若该位置不为null且相等,则替换value
若该位置不为null且不相等,则向后继续比较(指链表或红黑树)
- 第一次添加table为16,临界值为12(16*0.75)
- 以后再扩容,table为原来的2倍(32,64…),临界值也扩容(24,48…),依次类推
- 若一条链表(不包括table内) >= TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_CAPACITY (默认64),就会进行树化 (红黑树)
若一条链表的数据 >= 8,但table的大小并未满足 >= 64, 这是链表不会树化,而是增大table的容量
Hashtable
特点
Map
的实现类- 存放键值对
key
与value
都不能为null
,否则会抛出异常:NullPointerException
- 使用方法与
HashMap
基本相同 - 线程安全
Properties
特点
- 继承自Hashtable,并且是实现了Map接口
- 使用特点与Hashtable类型
- 还可用于xxx.properties文件中,加载到Properties类对象,并进行读取和修改
TreeMap
特点
- 对添加的(key, value),能够进行排序
1、当时调用的默认构造器时,会按照自然排序
TreeMap treeMap = new TreeMap();
treeMap.put("jack", "杰克");
treeMap.put("tom", "汤姆");
treeMap.put("kristina", "库瑞丝缇努普");
treeMap.put("smith", "斯密斯");
System.out.println(treeMap); //{jack=杰克, kristina=库瑞丝缇努普, smith=斯密斯, tom=汤姆}
2、可以自己选择排序方式,例如:按照key的长度大小排序
TreeMap treeMap = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
treeMap.put("jack", "杰克");
treeMap.put("tom", "汤姆");
treeMap.put("kristina", "库瑞丝缇努普");
treeMap.put("smith", "斯密斯");
System.out.println(treeMap); // {tom=汤姆, jack=杰克, smith=斯密斯, kristina=库瑞丝缇努普}
treeMap.put("hsp", "韩顺平"); //因为 hsp 与 tom 长度都为3,所以在这种条件下,算为相同的key
System.out.println(treeMap); // {tom=韩顺平, jack=杰克, smith=斯密斯, kristina=库瑞丝缇努普}
- 根据比较器的规则,进行排序的底层局部代码,(二叉排序树?)
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else {
V oldValue = t.value;
if (replaceOld || oldValue == null) {
t.value = value;
}
return oldValue;
}
Collections工具类
- 是一个操作
Set
、List
、和Map
等集合的工具类 Collections
种提供了一系列 静态方法 对集合元素进行排序、查询、修改等操作
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
1、reverse(List):反转
Collections.reverse(list);
System.out.println(list); [milan, king, smith, tom]
2、shuffle: 对List集合元素进行随机排序
Collections.shuffle(list);
System.out.println(list); [smith, king, milan, tom]
3、sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
Collections.sort(list);
System.out.println(list); [king, milan, smith, tom]
4、sort(List,Comparator):按照指定的 Comparator 进行排序
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
System.out.println(list); [tom, king, smith, milan]
5、swap(List,int,int) : 将指定 list 集合种的 i 处元素和 j 处元素进行交换
Collections.swap(list, 0, 1);
System.out.println(list); [smith, tom, king, milan]
6、Object max(Collection):根据自然排序,返回最大元素
System.out.println(Collections.max(list)); tom
7、Object max(Collection,Comparator): 根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object maxObject = Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
System.out.println(maxObject); smith
8、min 求最小 同上
9、int frequency(Collection,object):返回指定集合中指定元素的出现次数
System.out.println(Collections.frequency(list,"tom")); 1
10、void copy(List dest,List src): 将src中的内容复制到dest中
ArrayList dest = new ArrayList();
// Collections.copy(dest,list);
// System.out.println(dest); // 会抛出异常,因为src的size>dest的size(此时为null)
for (int i = 0; i < list.size(); i++) {
dest.add("");
}
Collections.copy(dest,list);
System.out.println(dest); [tom, smith, king, milan]
11、boolean replaceAll(List list,Object oldval,newVal):使用新值替换 list 对象的**所有旧值**
Collections.replaceAll(list,"tom","汤姆");
System.out.println(list); [汤姆, smith, king, milan]