javase之集合
集合分类
从大的类分Map和Connection
Map的子接口有HashMap、TreeMap、HashTable、ConcurrentHashMap、Properties
Connection有两个大的子接口:Set和List
Set的实现有HashSet、TreeSet、LinkedHashSet
List的实现有ArrayList、LinkedList、Vector以及Stack
集合基础
集合的特点
集合相比数组有两个主要特点:
- 存储对象而不能存储基本数据类型(数组可以存储基本数据类型)
- 长度可变容量自增(数组长度固定)
List、Set、Map的区别
- List和Set都是Connction的子接口,List的实现有ArrayList、LinkedList、Stack、Vector。Set的实现有HashSet、TreeSet、LinkedHashSet。他们两个的区别主要是以下两点:
- List元素可以重复,元素有序、有索引(从0开始)
- Set元素不可以重复,元素无序。(除了TreeSet:有序唯一)
- Map是一个键值对的集合,key:无序,唯一。value:可以重复。特别记住Map集合中:key一定是唯一的不可以重复的。Map集合的特点就两个存储键值对和key唯一。
在检索的时候只需要给出key就会返回对应的value值
使用List和Set检出集合中的重复元素
利用set集合元素不重复的特点进行检出
package com.test.day02;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @ClassName Prop
* @Description
* @Author 周志强
* @Date 2021/4/27 15:07
* @Version 1.0
*/
public class Prop {
public static void main(String[] args) {
//初始化interList
List<Integer> integerList=new ArrayList<>();
integerList.add(15);
integerList.add(15);
integerList.add(12);
integerList.add(1);
integerList.add(5);
integerList.add(35);
integerList.add(1);
Set<Integer> set=new HashSet<>();
//重复集合
List<Integer> repeatList=new ArrayList<>();
for (int i = 0; i < integerList.size(); i++) {
Integer value = integerList.get(i);
if (set.contains(value)) {
repeatList.add(value);
} else {
set.add(value);
}
}
for (Integer integer : repeatList) {
System.out.println(integer);
}
}
}
集合底层数据结构
- Conneciton
- List
- ArrayList:Object数组
- LinkedList:双向循环链表
- Vector::Object数组
- Set
- HashSet::底层通过HashMap实现
- TreeSet:红黑树(自平衡的排序二叉树)
- LinkedHashSet::底层通过LinkedHashMap实现
- 了解即可
- Map
- HashMap:JDK1.8 之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的( "拉链法”解决冲突) JDK1.8以后在解决哈希冲突时了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
- LinkedHashMap:LinkedHashMap 继承自HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
- HashTable:数组+ 链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。
- TreeMap:红黑树。
集合快速失败机制(fail-fast)
- 当多个线程操作集合的时候就会触发这个机制。
- 比如当一个线程通过Iterator进行遍历,另外一个线程改变它的结构(不是内容)此时就会触发快速失败机制。
- 原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个modCount变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext0/next0遍历下一个元素之前,都会检modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。
- 解决方法:使用CopyOnWriteArrayList来替换ArrayList
如何确保一个集合不能被修改
- 可以使用Collections. unmodifiableC ollection(C ollection c)方法来创建一个只读集合,这样改变集合的任何操作都会抛出Java. lang.UnsupportedOperationException异常。
- 代码实例
package com.test.day02;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @ClassName Prop
* @Description
* @Author 周志强
* @Date 2021/4/27 15:07
* @Version 1.0
*/
public class Prop {
public static void main(String[] args) {
List<String> stringList=new CopyOnWriteArrayList<>();
stringList.add("aa");
stringList.add("bb");
stringList.add("cc");
stringList.add("dd");
Collection<String> stringCollection = Collections.unmodifiableCollection(stringList);
for (String s : stringCollection) {
System.out.println(s);
}
}
}
collection接口
Iterator迭代器
Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection
中使用迭代器方法来获取迭代器实例。迭代器取代了Java集合框架中的
Enumeration,迭代器允许调用者在迭代过程中移除元素。
因为所有Collection接继承了Iterator 迭代器。
- 使用方法
package com.test.day02;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @ClassName Prop
* @Description
* @Author 周志强
* @Date 2021/4/27 15:07
* @Version 1.0
*/
public class Prop {
public static void main(String[] args) {
List<String> stringList=new CopyOnWriteArrayList<>();
stringList.add("aa");
stringList.add("bb");
stringList.add("cc");
stringList.add("dd");
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Iterator的特点
Iterator的特点是只能单向遍历,但是更加安全,因为它可以确保,在当前遍历
的集合元素被更改的时候,就会抛出ConcurrentModificationException 异
常。
Iteratro和ListIterator的区别
- Iterator可以遍历Set和List 集合,而Listlterator 只能遍历List。
- Iterator只能单向遍历,而Listlterator 可以双向遍历(向前/后遍历)。