目录
一、集合继承关系图
Java 集合主要分三大类,分别是List、Set、Map,而List和Set继承自Collection,整体关系如下图。
另外Cellections是用来操作集合的工具类,Arrays是用来操作数组的工具类。
二、Collection 接口
Collection 接口的主要作用是使得程序可以更方便地处理和操作集合中的对象。提供了添加、删除、遍历和查找元素的方法,以及获取集合大小和判断集合是否为空的方法。
1、add:向集合中添加指定的元素,返回是否添加成功。
2、addAll:将另一个集合中的所有元素添加到当前集合中,返回是否添加成功。
3、remove:从集合中移除指定的元素,返回是否移除成功。
4、removeAll:移除当前集合中与另一个集合中相同的所有元素,返回是否有元素被移除。
5、retainAll:仅保留与另一个集合相同的元素,移除其他元素,返回是否有元素被移除。
6、clear:清空集合,移除所有元素。
7、size:返回集合中元素的数量。
8、isEmpty:判断集合是否为空。
9、contains:判断集合是否包含指定的元素。
10、containsAll:判断集合是否包含另一个集合中的所有元素。
11、toArray:将集合中的元素转换为数组。
12、terator:返回迭代器,用于遍历集合中的元素。
13、stream():返回一个流,可用于进行流式操作。
三、List 接口及其实现类
List接口存储一组有序、不唯一的对象。List 接口实现了动态数组(ArrayList)和链表(LinkedList)等常用数据结构,可以根据实际需求选择不同的实现类。
List 接口的特点是可以通过索引访问和操作元素,可以按照元素的插入顺序进行遍历,允许存储重复的元素。与其他集合接口相比,List 接口更适合需要通过索引进行元素操作的场景,如需要在特定位置插入、删除元素的情况。
1、ArrayList 是一个长度可变的数组,可遍历元素和使用下标随机访问元素。
2、LinkedList 用链表存储方式实现,用于需要频繁插入和删除中间节点的操作。
3、Vector与 ArrayList 类似,但是是线程安全的,性能较差。在多线程环境中使用,或者在性能要求不高的情况下使用。
4、Stack基于 Vector 实现的栈(后进先出)数据结构。
5、CopyOnWriteArrayList 线程安全的 ArrayList 变体,适用于读多写少的场景,因为写操作会复制整个数据集。
(1)ArrayList 使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个ArrayList
ArrayList list = new ArrayList();
//添加元素
list.add(testInfo1);//默认自动扩展长度10
list.add(testInfo2);
list.add(testInfo3);
list.add(testInfo4);
list.add(1, testInfo5);
//删除元素
list.remove(3);
list.remove(testInfo2);
//判断列表中是否包含某个元素
if(list.contains(testInfo1)){
System.out.println("集合包含对象 testInfo1");
}
else{
System.out.println("集合不包含对象 testInfo1");
}
//循环查询1
for (int index = 0; index < list.size(); index++) {
Object obj = list.get(index);
TestInfo testInfo = (TestInfo)obj;
System.out.println("第一次循环输出集合元素 "+testInfo.getName());
}
//循环查询2
for (Object obj : list) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("第二次循环输出集合元素 "+testInfo.getName());
}
//清空集合
list.clear();
//判断一个集合是否为空
if(list.isEmpty()){
System.out.println("集合为空");
}
else{
System.out.println("集合不为空");
}
(2)LinkedList 使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个LinkedList
LinkedList list = new LinkedList();
//添加元素
list.add(testInfo1);
list.addFirst(testInfo2);
list.addLast(testInfo3);
list.addFirst(testInfo4);
list.addLast(testInfo5);
//删除元素
list.removeFirst();
//循环查询1
for (int index = 0; index < list.size(); index++) {
Object obj = list.get(index);
TestInfo testInfo = (TestInfo)obj;
System.out.println("第一次循环输出集合元素 "+testInfo.getName());
}
list.removeLast();
//循环查询2
for (Object obj : list) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("第二次循环输出集合元素 "+testInfo.getName());
}
(3)Vector 使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 Vector
Vector vector = new Vector();
//添加元素
vector.add(testInfo1);
vector.add(testInfo2);
vector.add(testInfo3);
vector.add(testInfo4);
vector.add(testInfo5);
//删除元素
vector.remove(testInfo1);
//循环查询
for (int index = 0; index < vector.size(); index++) {
Object obj = vector.get(index);
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
vector.removeAllElements();
(4)Stack使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 Stack
Stack list = new Stack();
//添加元素
list.push(testInfo1);
list.push(testInfo2);
list.push(testInfo3);
list.push(testInfo4);
list.push(testInfo5);
//循环查询
for (; list.size() > 0; ) {
Object obj = list.pop();
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
list.removeAllElements();
(5)CopyOnWriteArrayList使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 CopyOnWriteArrayList
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
//添加元素
list.add(testInfo1);
list.add(testInfo2);
list.add(testInfo3);
list.add(testInfo4);
list.add(testInfo5);
//删除元素
list.remove(testInfo2);
//循环查询1
for (int index = 0; index < list.size(); index++) {
Object obj = list.get(index);
TestInfo testInfo = (TestInfo)obj;
System.out.println("第一次循环输出集合元素 "+testInfo.getName());
}
//循环查询2
for (Object obj : list) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("第二次循环输出集合元素 "+testInfo.getName());
}
(6)测试相关的其他类
public static class TestInfo {
private int id;
private String name;
public TestInfo(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class TestCompareInfo extends TestInfo implements Comparable {
public TestCompareInfo(int id, String name) {
super(id, name);
}
@Override
public int compareTo(Object o) {
return 0;
}
}
public static class TestInfoComparator implements Comparator<TestInfo> {
@Override
public int compare(TestInfo t1, TestInfo t2) {
return Integer.compare(t1.getId(), t2.getId());
}
}
四、Set接口及其实现类
Set接口存储一组无序、唯一的对象。它是处理去重数据的常用选择,并提供了高效的查找和判断元素存在性的功能。常见的 Set 接口的实现类包括 HashSet、TreeSet 和 LinkedHashSet 等。
1、HashSet 基于散列表(哈希表)实现,存储唯一元素,不保证元素的顺序。
2、LinkedHashSet 在 HashSet 的基础上,使用链表维护插入顺序,因此能够保持插入顺序。
3、TreeSet 基于红黑树实现,存储唯一元素,并按照元素的自然顺序(或者提供的比较器)进行排序。
3、EnumSet:专门用于存储枚举类型的集合,基于位向量实现,非常高效。
4、CopyOnWriteArraySet 线程安全的 Set 变体,底层基于 CopyOnWriteArrayList,适用于读多写少的场景。
(1)HashSet使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个HashSet
HashSet set = new HashSet();
//添加元素
set.add(testInfo1);
set.add(testInfo2);
set.add(testInfo3);
set.add(testInfo4);
set.add(testInfo5);
set.add(testInfo1);
set.add(testInfo1);
set.add(testInfo2);
//删除元素
set.remove(testInfo5);
//循环查询
for (Object obj : set) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
(2)LinkedHashSet使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 HashSet
LinkedHashSet set = new LinkedHashSet();
//添加元素
set.add(testInfo1);
set.add(testInfo2);
set.add(testInfo3);
set.add(testInfo4);
set.add(testInfo5);
set.add(testInfo1);
set.add(testInfo1);
set.add(testInfo2);
//删除元素
set.remove(testInfo5);
//循环查询
for (Object obj : set) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
(3)TreeSet使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
TestInfoComparator comparator = new TestInfoComparator();
//创建一个TreeSet
TreeSet set = new TreeSet(comparator);//这里如果不传入comparator, 添加的对象就要使用类似于TestCompareInfo的类
//添加元素
set.add(testInfo1);
set.add(testInfo2);
set.add(testInfo3);
set.add(testInfo4);
set.add(testInfo5);
set.add(testInfo1);
set.add(testInfo1);
set.add(testInfo2);
//删除元素
set.remove(testInfo5);
//循环查询
for (Object obj : set) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
(4)EnumSet使用方法
//1、创建 EnumSet
// 创建一个包含所有枚举值的 EnumSet
EnumSet<Weekday> set1 = EnumSet.allOf(Weekday.class);
// 创建一个空的 EnumSet,并指定枚举类型
EnumSet<Weekday> set2 = EnumSet.noneOf(Weekday.class);
// 创建一个包含指定枚举值的 EnumSet
EnumSet<Weekday> set3 = EnumSet.of(Weekday.SATURDAY, Weekday.SUNDAY);
// 创建一个范围内的 EnumSet,包含起始和结束之间的所有枚举值:
EnumSet<Weekday> set4 = EnumSet.range(Weekday.MONDAY, Weekday.FRIDAY);
// 2、添加和删除元素
EnumSet<Weekday> set5 = EnumSet.noneOf(Weekday.class);
// 添加一个枚举值到 EnumSet:
set5.add(Weekday.MONDAY);
set5.add(Weekday.TUESDAY);
set5.add(Weekday.WEDNESDAY);
// 删除一个枚举值从 EnumSet:
set5.remove(Weekday.MONDAY);
// 3、检查元素是否存在
// 检查 EnumSet 是否包含指定枚举值
boolean contains = set5.contains(Weekday.MONDAY);
// 4、大小和清空操作
// 获取 EnumSet 的大小(包含的枚举值数量)
int size = set5.size();
// 清空 EnumSet 中的所有元素:
// set5.clear();
// 5、遍历 EnumSet
// 使用迭代器遍历 EnumSet:
Iterator<Weekday> iterator = set5.iterator();
while (iterator.hasNext()) {
Weekday value = iterator.next();
System.out.println(value);
}
// 使用增强的 for 循环遍历 EnumSet:
for (Weekday value : set5) {
System.out.println(value);
}
(5)CopyOnWriteArraySet使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 CopyOnWriteArraySet
CopyOnWriteArraySet set = new CopyOnWriteArraySet();
//添加元素
set.add(testInfo1);
set.add(testInfo2);
set.add(testInfo3);
set.add(testInfo4);
set.add(testInfo5);
set.add(testInfo1);
set.add(testInfo1);
set.add(testInfo2);
//删除元素
set.remove(testInfo5);
//循环查询
for (Object obj : set) {
TestInfo testInfo = (TestInfo)obj;
System.out.println("循环输出集合元素 "+testInfo.getName());
}
public static class TestInfo {
private int id;
private String name;
public TestInfo(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class TestCompareInfo extends TestInfo implements Comparable {
public TestCompareInfo(int id, String name) {
super(id, name);
}
@Override
public int compareTo(Object o) {
return 0;
}
}
public static class TestInfoComparator implements Comparator<TestInfo> {
@Override
public int compare(TestInfo t1, TestInfo t2) {
return Integer.compare(t1.getId(), t2.getId());
}
}
public enum Weekday {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
五、Map接口及其实现类
用于存储键值对(key-value)的数据结构。Map 接口提供了一种将键映射到值的方式,它不允许键重复,并且可以根据键快速找到对应的值。常见的 Map 接口的实现类包括 HashMap、TreeMap 和 LinkedHashMap 等。
1、HashMap 基于散列表(哈希表)实现,存储键值对,键是唯一的。不保证键值对的顺序。
2、LinkedHashMap 在 HashMap 的基础上,使用链表维护插入顺序或访问顺序,能够保持插入顺序或按照访问顺序遍历键值对。
3、TreeMap 基于红黑树实现,存储键值对,并按照键的自然顺序(或者提供的比较器)进行排序。
4、WeakHashMap 与 HashMap 类似,但对于没有被其他对象引用的键,不会阻止垃圾回收。
5、EnumMap 专门用于存储枚举类型的键的集合,内部基于数组实现,非常高效。
6、IdentityHashMap 使用引用相等而不是值相等来比较键,对于对象引用的比较非常严格。
7、ConcurrentHashMap线程安全的 HashMap 变体,支持并发访问,分段锁机制提高了并发性能。
8、Properties一个特殊的 Map 实现,用于处理属性文件,键和值都必须为字符串类型。
9、HashTable 与 HashMap 类似,但是是线程安全的,性能较差。在多线程环境中使用,或者在性能要求不高的情况下使用。
(1)HashMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 HashMap
HashMap map = new HashMap();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4, testInfo4);
map.put(testInfo5, testInfo5);
map.put(testInfo5.getId(), testInfo5);
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
TestInfo testInfo = null;
if(obj instanceof Integer){
int id = (int)obj;
testInfo = (TestInfo)map.get(id);
}
else{
testInfo = (TestInfo)obj;
}
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
Object key = me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
(2)LinkedHashMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 LinkedHashMap
LinkedHashMap map = new LinkedHashMap();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4.getId(), testInfo4);
map.put(testInfo5.getId(), testInfo5);
//map.put(testInfo5, testInfo5); 混合添加不能再使用,因为他要排序
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
int id = (int)obj;
TestInfo testInfo = (TestInfo)map.get(id);
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
int key = (int)me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
(3)TreeMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 TreeMap
TreeMap map = new TreeMap();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4.getId(), testInfo4);
map.put(testInfo5.getId(), testInfo5);
map.put(testInfo5.getId(), testInfo5);
//map.put(testInfo5, testInfo5); 混合添加不能再使用,因为他要排序
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
int id = (int)obj;
TestInfo testInfo = (TestInfo)map.get(id);
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
int key = (int)me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
(4)WeakHashMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 WeakHashMap
WeakHashMap map = new WeakHashMap ();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4, testInfo4);
map.put(testInfo5, testInfo5);
map.put(testInfo5.getId(), testInfo5);
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
TestInfo testInfo = null;
if(obj instanceof Integer){
int id = (int)obj;
testInfo = (TestInfo)map.get(id);
}
else{
testInfo = (TestInfo)obj;
}
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
Object key = me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
(5)EnumMap使用方法
// 1、创建 EnumMap
// 创建一个空的 EnumMap,并指定枚举类型
EnumMap<Weekday, Integer> map1 = new EnumMap<>(Weekday.class);
// 2、添加和更新键值对
// 添加一个键值对到 EnumMap
map1.put(Weekday.MONDAY, 10);
map1.put(Weekday.TUESDAY, 2);
map1.put(Weekday.WEDNESDAY, 3);
// 更新一个键对应的值
map1.put(Weekday.MONDAY, 1);
// 3、获取和删除键值对
// 获取指定键对应的值
Integer value1 = map1.get(Weekday.MONDAY);
// 删除指定键对应的键值对
map1.remove(Weekday.MONDAY);
// 4、检查键是否存在
// 检查 EnumMap 是否包含指定键
boolean containsKey = map1.containsKey(Weekday.MONDAY);
// 5、大小和清空操作
// 获取 EnumMap 中键值对的数量
int size = map1.size();
// 清空 EnumMap 中的所有键值对
// map1.clear();
// 6、遍历键值对
// 使用迭代器遍历 EnumMap 的键值对
Iterator<Map.Entry<Weekday, Integer>> iterator = map1.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Weekday, Integer> entry = iterator.next();
Weekday key = entry.getKey();
Integer value = entry.getValue();
System.out.println("key="+key+",value="+value);
}
// 使用增强的 for 循环遍历 EnumMap 的键值对
for (Map.Entry<Weekday, Integer> entry : map1.entrySet()) {
Weekday key = entry.getKey();
Integer value = entry.getValue();
System.out.println("key="+key+",value="+value);
}
(6)IdentityHashMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 IdentityHashMap
IdentityHashMap map = new IdentityHashMap ();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4, testInfo4);
map.put(testInfo5, testInfo5);
map.put(testInfo5.getId(), testInfo5);
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
TestInfo testInfo = null;
if(obj instanceof Integer){
int id = (int)obj;
testInfo = (TestInfo)map.get(id);
}
else{
testInfo = (TestInfo)obj;
}
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
Object key = me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
(7)ConcurrentHashMap使用方法
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
//创建一个 ConcurrentHashMap
ConcurrentHashMap map = new ConcurrentHashMap ();
//添加元素
map.put(testInfo1.getId(), testInfo1);
map.put(testInfo2.getId(), testInfo2);
map.put(testInfo3.getId(), testInfo3);
map.put(testInfo4, testInfo4);
map.put(testInfo5, testInfo5);
map.put(testInfo5.getId(), testInfo5);
//删除元素
map.remove(testInfo3.getId());
//根据Key循环查询
Set keys = map.keySet();
for (Object obj : keys) {
TestInfo testInfo = null;
if(obj instanceof Integer){
int id = (int)obj;
testInfo = (TestInfo)map.get(id);
}
else{
testInfo = (TestInfo)obj;
}
System.out.println("根据Key 循环输出元素 "+testInfo.getName());
}
//根据entry循环查询
Set entry = map.entrySet();
for (Object obj : entry) {
Map.Entry me = (Map.Entry)obj;
Object key = me.getKey();
TestInfo testInfo = (TestInfo)me.getValue();
System.out.println("根据Entry 循环输出元素 "+testInfo.getName());
}
六、Generics泛型
Java 泛型是一种强大的编程机制,它允许你在创建类、接口和方法时定义参数类型,从而实现类型安全和代码重用。
给集添加泛型约束的举例:
public static void main(String[] args) {
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
TestCompareInfo testInfo6 = new TestCompareInfo(6, "测试信息5");
TestCompareInfo testInfo7 = new TestCompareInfo(7, "测试信息5");
TestInfoComparator comparator = new TestInfoComparator();
List list1 = new ArrayList<TestInfo>();
List list2 = new LinkedList<TestInfo>();
Set set1 = new HashSet<TestInfo>();
Set set2 = new TreeSet<TestInfo>();
Map<Integer, TestInfo> map1 = new HashMap<Integer, TestInfo>();
Map<Integer, TestInfo> map2 = new LinkedHashMap<Integer, TestInfo>();
Map<Integer, TestInfo> map3 = new TreeMap<Integer, TestInfo>();
//使用传入比较器的 TreeMap
Map<TestInfo, TestInfo> map4 = new TreeMap<TestInfo, TestInfo>(comparator);
Map<TestInfo, TestInfo> map5 = new TreeMap<TestInfo, TestInfo>(comparator);
//使用实现比较接口的 TreeMap
Map<TestCompareInfo, TestInfo> map6 = new TreeMap<TestCompareInfo, TestInfo>();
Map<TestCompareInfo, TestInfo> map7 = new TreeMap<TestCompareInfo, TestInfo>();
map1.put(testInfo1.getId(), testInfo1);
map2.put(testInfo2.getId(), testInfo2);
map3.put(testInfo3.getId(), testInfo3);
map4.put(testInfo4, testInfo4);
map5.put(testInfo5, testInfo4);
map6.put(testInfo6, testInfo6);
map7.put(testInfo7, testInfo7);
Set<Map.Entry<Integer, TestInfo>> entries = map1.entrySet();
}
public static class TestInfo {
private int id;
private String name;
public TestInfo(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class TestCompareInfo extends TestInfo implements Comparable {
public TestCompareInfo(int id, String name) {
super(id, name);
}
@Override
public int compareTo(Object o) {
return 0;
}
}
public static class TestInfoComparator implements Comparator<TestInfo> {
@Override
public int compare(TestInfo t1, TestInfo t2) {
return Integer.compare(t1.getId(), t2.getId());
}
}
七、集合和数组工具类
1、Collections 工具类
(1)sort:对列表进行排序。
(2)binarySearch:在已排序的列表中使用二分查找来查找指定的元素。
(3)reverse:反转列表中元素的顺序。
(4)shuffle:随机重排列表中的元素。
(5)min:返回集合中的最小元素。
(6)max:返回集合中的最大元素。
(7)unmodifiableList:返回一个不可修改的列表视图。
(8)synchronizedMap:返回一个线程安全的映射。
(9)ingleton:返回一个包含单个指定对象的不可修改的集合。
(10)emptyList:返回一个空的不可修改的列表。
(11)emptySet:返回一个空的不可修改的集合。
TestCompareInfo testInfo1 = new TestCompareInfo(1, "测试信息1");
TestCompareInfo testInfo2 = new TestCompareInfo(2, "测试信息2");
TestCompareInfo testInfo3 = new TestCompareInfo(3, "测试信息3");
TestCompareInfo testInfo4 = new TestCompareInfo(4, "测试信息4");
TestCompareInfo testInfo5 = new TestCompareInfo(5, "测试信息5");
List<TestCompareInfo> list = new ArrayList<TestCompareInfo>();
list.add(testInfo1);
list.add(testInfo2);
list.add(testInfo3);
list.add(testInfo4);
list.add(testInfo5);
//Collections.sort(list);
System.out.println("最小值 "+ Collections.min(list).getName());
System.out.println("最大值 "+ Collections.max(list).getName());
System.out.println("搜索 testInfo3 位置 = "+ Collections.binarySearch(list, testInfo3));
// 返回包含指定元素的不可变 List。
// Collections.nCopies();
// 返回只包含一个指定元素的不可变 List。
// Collections.singletonList()
// 返回只包含一个指定元素的不可变 Set。
// Collections.singleton()
// 返回空的不可变 Set。
// Collections.emptySet()
2、Arrays工具类
(1)sort:对数组进行排序。
(2)binarySearch:在已排序的数组中使用二分查找来查找指定的元素。
(3)fill:将数组中的所有元素填充为指定的值。
(4)copyOfRange:复制原始数组的指定范围部分,生成一个新的数组。
(5)equals:判断两个数组是否相等。
(6)asList:将指定的元素转换为固定大小的列表。
TestCompareInfo testInfo1 = new TestCompareInfo(1, "测试信息1");
TestCompareInfo testInfo2 = new TestCompareInfo(2, "测试信息2");
TestCompareInfo testInfo3 = new TestCompareInfo(3, "测试信息3");
TestCompareInfo testInfo4 = new TestCompareInfo(4, "测试信息4");
TestCompareInfo testInfo5 = new TestCompareInfo(5, "测试信息5");
List<TestCompareInfo> list = new ArrayList<TestCompareInfo>();
list.add(testInfo3);
list.add(testInfo1);
list.add(testInfo4);
list.add(testInfo2);
list.add(testInfo5);
// 转换为数组
TestCompareInfo[] array = list.toArray(new TestCompareInfo[0]);
// 使用 Arrays.sort 对数组进行排序
Arrays.sort(array);
// 转换回 ArrayList
ArrayList<TestCompareInfo> sortedList = new ArrayList<>(Arrays.asList(array));
//循环查询2
for (TestCompareInfo testInfo : sortedList) {
System.out.println("排序后结果 "+testInfo.getName());
}
// 将数组转换为固定大小的 List,不支持插入和删除操作。
List list1 = Arrays.asList(new int[]{ 1, 2 ,3, 4, 4});
八、迭代器遍历集合
Iterator 提供了一种安全、抽象化的遍历方式,适用于多种集合实现,同时支持元素的移除操作,使代码更加健壮和清晰。主要优势如下:
(1)安全遍历集合: Iterator 提供了一种安全的方式来遍历集合,尤其在多线程环境中,可以避免遍历过程中的并发修改问题。遍历过程中如果尝试修改集合,会抛出 ConcurrentModificationException 异常,从而提醒开发者注意并发问题。
(2)支持移除元素: Iterator 提供了 remove() 方法,允许你在遍历过程中删除集合中的元素。这是使用增强 for 循环无法实现的功能,可以避免在遍历过程中删除元素时引发的问题。
(3)抽象化遍历方式: 使用 Iterator 可以将遍历逻辑与具体的集合实现分离,使你能够以一种统一的方式遍历不同类型的集合,无论是数组、列表、集或映射。
(4)避免索引操作: 使用 Iterator 可以避免使用索引进行遍历,从而使代码更加清晰,不会因索引操作而引入错误。
(5)遍历途中插入元素: 使用 Iterator 遍历集合时,可以在遍历过程中插入新元素,而不会影响当前遍历的内容。这是在使用增强 for 循环时无法做到的。
TestInfo testInfo1 = new TestInfo(1, "测试信息1");
TestInfo testInfo2 = new TestInfo(2, "测试信息2");
TestInfo testInfo3 = new TestInfo(3, "测试信息3");
TestInfo testInfo4 = new TestInfo(4, "测试信息4");
TestInfo testInfo5 = new TestInfo(5, "测试信息5");
ArrayList list = new ArrayList();
list.add(testInfo1);
list.add(testInfo2);
list.add(testInfo3);
list.add(testInfo4);
list.add(testInfo5);
Iterator itor = list.iterator();
while(itor.hasNext()){
Object obj = itor.next();
TestInfo testInfo = (TestInfo)obj;
System.out.println("第二次循环输出集合元素 "+testInfo.getName());
}
九、线程安全的集合
线程安全的集合类在java.util.concurrent包下面,他们提供了在多线程环境下安全地进行操作的方式,可以根据具体的需求选择适合的集合类来使用。使用方法与普通集合差不大,请参考普通集全使用方法。
需要注意的是,虽然这些集合类提供了线程安全的操作,但在特定的场景下可能需要额外的同步措施,以确保操作的原子性和一致性。