本文最后更新于 59天前,其中的信息可能已经有所发展或是发生改变。若对文章内容存疑,或是本文的转载部分侵犯了您的权益,请联系博主 3240572824@qq.com
Java的常用数据容器有数组、集合等,其中数组的长度固定,在创建后无法改变。相较之下,作为一种动态长度的数据容器,集合提供了更丰富的操作方法,又因为适用于不同的实际需要,集合基于不同的底层数据结构分为单列集合与双列集合。
单列集合
存储单个元素的容器类
Collection
Collection是单列接口的顶层接口,其功能所有单列接口都可继承使用
常见功能方法
- add() 添加元素
- clear() 清空元素
- remove() 删除元素
- contains() 判断是否包含某元素
- isEmpty() 判断集合是否为空
- size() 获取集合长度
三种遍历
迭代器遍历
迭代器类Iterator是集合的专用遍历方式
核心:每次执行next()方法时会执行获取元素、移动指针两步操作
增强for遍历
底层基于迭代器的遍历方式
格式:
for(数据格式 变量名:集合/数组){
}
注意:对增强for中的变量做修改,并不影响集合的原数据(for循环中的变量仅是一个第三方变量)
示例:
Collection<String>coll=new ArrayList<>();
coll.add("zhangsan");
coll.add("lisi");
coll.add("wangwu");
for(String str:coll){
str="ash";
System.out.println(str);//ash
}
System.out.println(coll);//[zhangsan, lisi, wangwu]
Lambda表达式遍历
底层是for循环遍历集合
完整匿名内部类:
coll.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
Lambda:
coll.forEach(s -> System.out.println(s));
List集合
元素存取过程有序、可重复、有索引
因为有了索引值,所以其多了一些与索引操作相关的方法
Set集合
元素存取过程无序、不重复、无索引
HashSet
哈希值:对象的整数表现形式
哈希表:可以通过哈希值确定键值对的位置
- 若未重写hashCode方法,计算出的哈希值不同
- 若已重写hashCode方法,不同对象只要属性值相同,计算出的哈希值一样
- 小部分情况下,不同属性值或不同地址值计算出的哈希值亦可能相等(哈希碰撞)
为什么HashSet属于单列集合,却与双列集合的键值对有关?
下方是来自GPT的回答
LinkedHashSet
有序 不重复 无索引
TreeSet
不重复 无索引 可排序
使用场景
- 想要集合元素可重复 ArrayList 基于数组 (用的最多)
- 想要集合元素可重复 且当前的增删操作多于查询 LinkedList 基于链表
- 想对集合元素去重 HashSet 基于哈希表 (用的最多)
- 想对集合元素去重 且保证存取顺序 LinkedHashSet 基于哈希表和双链表(效率低于HashSet)
- 想对集合元素排序 TreeSet 基于红黑树(后续亦可用List集合实现排序)
双列集合
存储键值对的容器类
特点:
- 双列集合一次需要存一对数据,分别为键和值
- 键不可重复,值可以重复
- 键和值一一对应,每一个键只能找到自己的对应值
- 键+值这个整体,称之为“键值对”或者“键值对对象”,java中叫做“Entry对象”
Map
Map是双列集合的顶层接口,其功能所有的双列集合均可继承使用
常用功能方法
- put() 添加元素
- remove() 删除元素
- clear() 清空元素
- containsKey() 判断是否包含某元素
- isEmpty() 判断是否为空
- size() 获取集合长度
三种遍历
由键找值
Map<String,String> map=new HashMap<>();
map.put("尹志平","小龙女");
map.put("郭靖","穆念慈");
map.put("欧阳克","黄蓉");
//获取所有的键,放入一个单列集合
Set<String> keys=map.keySet();
for (String key : keys) {
// System.out.println(key);
// 利用键获取对应值 get
String value=map.get(key);
System.out.println(key+"="+value);
// 尹志平=小龙女
// 郭靖=穆念慈
// 欧阳克=黄蓉
}
获取并遍历Entries对象
Map<String,String> map=new HashMap<>();
map.put("尹志平","小龙女");
map.put("郭靖","穆念慈");
map.put("欧阳克","黄蓉");
// 通过键值对对象遍历
// 1 通过一个方法获取所有键值对对象,返回一个Set集合
Set<Map.Entry<String,String>>entries=map.entrySet();
// 2 遍历集合entries,得到其中的每一个键值对对象
for (Map.Entry<String, String> entry : entries) {
// 3 利用entry调用get方法获取键与值
String key=entry.getKey();
String value=entry.getValue();
System.out.println(key+"="+value);
// 尹志平=小龙女
// 郭靖=穆念慈
// 欧阳克=黄蓉
}
Lambda表达式遍历
Map<String, String> map = new HashMap<>();
map.put("鲁迅", "这句话是我说的");
map.put("曹操", "不可能绝对不可能");
map.put("刘备", "接着奏乐接着舞");
map.forEach((key, value) -> System.out.println(key + "=" + value));
// 刘备=接着奏乐接着舞
// 鲁迅=这句话是我说的
// 曹操=不可能绝对不可能
HashMap
无序 不重复 无索引
底层数据结构与HashSet一致,均为哈希表
LinkedHashMap
有序 不重复 无索引
底层数据结构也是哈希表 但多了一个双链表机制记录存储顺序
TreeMap
不重复 无索引 可排序
注意:
- 排序是对键的排序
- 通过实现Comparable接口,指定比较规则
- 或者在创建集合时传递Comparator比较器对象,指定比较规则
不可变集合
出于安全需要,不可被修改的集合,一旦创建,只能对其执行查询操作
各类集合对应的不可变集合分别为:
- List – List.of
- Set – Set.of
- Map – Map.of
Set<String> set = Set.of("zhangsan", "lisi", "wangwu");
System.out.println(set); // [zhangsan, wangwu, lisi]