Java集合详解
1.集合
1.1、什么是集合
在java中,集合(Collection)指的是一组数据容器,它可以存储多个对象,并且允许用户通过一些方法来访问与操作这些对象。java提供了一系列接口和类来支持不同类型的集合。 Collection
接口,主要用于存放单一元素; Map
接口,主要用于存放键值对。
1.2、collection集合常用方法
方法声明 | 功能描述 |
---|---|
boolean add(Object o) | 向集合中添加一个元素 |
boolean addAll(Collection c) | 将指定Collection中的所有元素添加到该集合中 |
void clear() | 删除该集合中的所有元素 |
boolean remove(Object o) | 删除该集合中指定的元素 |
boolean removeAll(Collection c) | 删除指定集合中的所有元素 |
boolean isEmpty() | 判断该集合是否为空 |
boolean contains(Object o) | 判断该集合中是否包含某个元素 |
boolean containsAll(Collection c) | 判断该集合中是否包含指定集合中的所有元素 |
Iterator iterator() | 返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合所有元素 |
int size() | 获取该集合元素个数 |
1.3、List接口简介
List接口继承自Collection接口,存取有序,有索引,允许存储重复的值。List接口主要有两个实现类,分别是ArrayList和LinkedList,List接口常用方法如下:
方法声明 | 功能描述 |
---|---|
void add(int index,Object element) | 将元素element插入在List集合的index处 |
boolean addAll(int index,Collection c) | 将集合c所包含的所有元素插入到List集合的index处 |
Object get(int index) | 返回集合索引index处的元素 |
Object remove(int index) | 删除index索引处的元素 |
Object set(int index, Object element) | 将索引index处元素替换成element对象,并将替换后的元素返回 |
int indexOf(Object o) | 返回对象o在List集合中出现的位置索引 |
int lastIndexOf(Object o) | 返回对象o在List集合中最后一次出现的位置索引 |
List subList(int fromIndex, int toIndex) | 返回从索引fromIndex(包括)到 toIndex(不包括)处所有元素集合组成的子集合 |
1.4、set接口简介
Set接口继承自Collection接口,它与Collection接口中的方法基本一致,Set接口中元素无序,不允许重复。Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储位置,具有良好的存取和查找性能。TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。
1.5、map接口简介
Map接口是一种双列集合,以键值对的方式存储数据,它的每个元素都包含一个键对象Key和值对象Value,键和值对象之间存在一种对应关系,称为映射。从Map集合中访问元素时,只要指定了Key,就能找到对应的Value。常用方法如下:
方法声明 | 功能描述 |
---|---|
void put(Object key, Object value) | 将指定的值与此映射中的指定键关联(可选操作) |
Object get(Object key) | 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null |
void clear() | 移除所有的键值对元素 |
V remove(Object key) | 根据键删除对应的值,返回被删除的值 |
int size() | 返回集合中的键值对的个数 |
boolean containsKey(Object key) | 如果此映射包含指定键的映射关系,则返回 true。 |
boolean containsValue(Object value) | 如果此映射将一个或多个键映射到指定值,则返回 true |
Set keySet() | 返回此映射中包含的键的 Set 视图 |
Collection values() | 返回此映射中包含的值的 Collection 视图 |
Set<Map.Entry<K,V>>entrySet() | 返回此映射中包含的映射关系的Set视图 |
2.List集合常用实现类
2.1、ArrayList
ArrayList底层基于数组实现,查询元素快,增删相对慢。
2.1.1、ArrayList长度可变的原理
- 当创建 ArrayList 集合容器的时候, 底层会存在一个长度为10个大小的空数组
- 当数组加满之后,会自动扩容原数组 1.5 倍大小的新数组
- 将原数组数据,拷贝到新数组中
- 将新元素添加到新数组
2.1.2、使用实例
@Test
public void testArrayList(){
//使用多态的方式创建ArrayList集合,存储字符串。
List<String> listStr = new ArrayList<>();
//添加元素到集合中
listStr.add("莫");
listStr.add("听");
listStr.add("穿");
listStr.add("林");
listStr.add("打");
listStr.add("叶");
listStr.add("声");
//获取指定索引处的元素,索引从0开始
String s1 = listStr.get(2); // 穿
//删除指定的元素
boolean flag = listStr.remove("穿"); //true
//遍历集合
System.out.println("---------------------使用for循环遍历-------------------------");
for(int i = 0;i<listStr.size();i++){
System.out.println(listStr.get(i));
}
System.out.println("---------------------使用增强for循环遍历-------------------------");
//增强for循环语法: for(数据类型 变量:集合) 变量表示集合中的每一个元素
for(String str:listStr){
System.out.println(str);
}
System.out.println("---------------------使用迭代器遍历-------------------------");
//获取迭代器对象
Iterator<String> iterator = listStr.iterator();
//循环遍历集合
while (iterator.hasNext()){ //判断是否还有下一个元素
String next = iterator.next(); //获取元素,并将指针往后移动一个位置
System.out.println(next);
}
}
2.1.3、迭代器遍历原理
2.2、LinkedList
2.2.1、实现原理
LinkedList 底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的
2.2.2、常用特有方法
方法声明 | 功能描述 |
---|---|
void add(int index, E element) | 在此列表中指定的位置插入指定的元素 |
void addFirst(Object o) | 将指定元素插入此列表的开头 |
void addLast(Object o) | 将指定元素添加到此列表的结尾 |
Object getFirst() | 返回此列表的第一个元素 |
Object getLast() | 返回此列表的最后一个元素 |
Object removeFirst() | 移除并返回此列表的第一个元素 |
Object removeLast() | 移除并返回此列表的最后一个元素 |
2.2.3、代码示例
public void testLinkedList(){
//创建集合
LinkedList<String> linkedList = new LinkedList<>();
//添加元素
linkedList.add("何");
linkedList.add("妨");
linkedList.add("吟");
linkedList.add("萧");
linkedList.add("且");
linkedList.add("徐");
linkedList.add("行");
//将自定元素插入列表开头
linkedList.addFirst(",");
//获取开头的第一个元素
String first = linkedList.getFirst(); //,
}
3.Set集合常用实现类
3.1、HashSet
HashSet 集合底层采取哈希表存储数据,它所存储的元素无序,不可重复的
//存储String字符串
@Test
public void testHashSet(){
//创建HashSet集合
HashSet<String> setStr = new HashSet<>();
setStr.add("竹");
setStr.add("杖");
setStr.add("芒");
setStr.add("鞋");
setStr.add("竹"); //向集合中添加重复元素
//遍历集合
Iterator<String> it = setStr.iterator(); // 获取Iterator对象
while (it.hasNext()) { // 通过while循环,判断集合中是否有元素
String obj = it.next();// 如果有元素,就通过迭代器的next()方法获取元素
System.out.println(obj);
}
}
4.Map接口
Map 集合是一种双列集合,每个元素包含两个数据
Map 集合的每个元素的格式:key = value(键值对元素)
key (键) : 不允许重复
value (值) : 允许重复
键和值是一一对应的,每个键只能找到自己对应的值
key + value 这个整体 我们称之为“键值对”或者“键值对对象” 在Java中使用Entry对象表示
4.1、map接口常用方法
方法声明 | 功能描述 |
---|---|
void put(Object key, Object value) | 将指定的值与此映射中的指定键关联(可选操作) |
Object get(Object key) | 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null |
void clear() | 移除所有的键值对元素 |
V remove(Object key) | 根据键删除对应的值,返回被删除的值 |
int size() | 返回集合中的键值对的个数 |
boolean containsKey(Object key) | 如果此映射包含指定键的映射关系,则返回 true。 |
boolean containsValue(Object value) | 如果此映射将一个或多个键映射到指定值,则返回 true |
Set keySet() | 返回此映射中包含的键的 Set 视图 |
Collection values() | 返回此映射中包含的值的 Collection 视图 |
Set<Map.Entry<K,V>>entrySet() | 返回此映射中包含的映射关系的Set视图 |
4.2、HashMap
HashMap集合是Map接口的一个实现类,用于存储键值映射关系,但HashMap集合没有重复的键并且键值无序。
@Test
public void testHashMap(){
//创建map集合
HashMap<String, String> strMap = new HashMap<>();
//存储键值对
strMap.put("name","苏东坡");
strMap.put("gender","男");
strMap.put("address","五湖四海");
//获取集合的大小
int size = strMap.size();
System.out.println("集合的长度为:"+size);
//通过键获取值
String name = strMap.get("name"); //苏东坡
//遍历map集合
System.out.println("-----------------通过键找值---------------------");
//调用keySet 方法,获取 Map 集合中所有的键,返回set集合
Set<String> keys = strMap.keySet();
//遍历set集合获取每一个键
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()){
//调用 get 方法, 根据键找值
String val = strMap.get(iterator.next());
System.out.println(val);
}
System.out.println("----------------------------------------------");
for(String str:keys){
System.out.println(strMap.get(str));
}
System.out.println("-----------------使用entrySet方法获取所有键值对象---------------------");
//调用 entrySet 方法获取所有的键值对对象
Set<Map.Entry<String, String>> kvs = strMap.entrySet();
//遍历 Set 集合, 获取每一个键值对对象
for (Map.Entry<String, String> kv:kvs){
//获取键
System.out.println("键:"+kv.getKey());
//获取值
System.out.println("值:"+kv.getValue());
}
System.out.println("-----------------lambda表达式---------------------");
strMap.forEach((k,v)->{
System.out.println(k +":" + v);
});
}
4.3、map集合练习
4.3.1、练习1
字符串 aababcabcdabcde,请统计字符串中每一个字符出现的次数,输出结果为: a(5)b(4)c(3)d(2)e(1)
//字符串 aababcabcdabcde,请统计字符串中每一个字符出现的次数,输出结果为: a(5)b(4)c(3)d(2)e(1)
@Test
public void testMap(){
//字符串 aababcabcdabcde,请统计字符串中每一个字符出现的次数
Map<Character,Integer> maps = new HashMap<>();
String str = "aababcabcdabcde";
//将字符串转换为 char类型的数组
char[] chars = str.toCharArray();
for (char ch : chars){
Integer i = maps.get(ch); //通过键取值
if (i==null){
maps.put(ch,1);
}else {
maps.put(ch, ++i);
}
}
StringBuilder sb = new StringBuilder();
Set<Character> s = maps.keySet(); //将TreeMap集合中所有键存到Set集合
for (Character key : s) {
Integer value = maps.get(key); //获取每个键的对应值
sb.append(key).append("(").append(value).append(")"); //将值添加到StringBuilder
}
String result = sb.toString(); //将StringBuilder转为String类型
System.out.println("result:" + result);
}
4.3.2、练习2
/*定义一个Map集合,键用表示省份名称,值表示市,但是市会有多个。
添加完毕后,遍历结果:
格式如下:
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
四川省 = 成都市,绵阳市,自贡市,攀枝花市,泸州市
*/
@Test
public void testMap2(){
HashMap<String, List<String>> mapList = new HashMap<>();
//2.创建单列集合存储市
ArrayList<String> city1 = new ArrayList<>();
city1.add("南京市");
city1.add("扬州市");
city1.add("苏州市");
city1.add("无锡市");
city1.add("常州市");
ArrayList<String> city2 = new ArrayList<>();
city2.add("武汉市");
city2.add("孝感市");
city2.add("十堰市");
city2.add("宜昌市");
city2.add("鄂州市");
ArrayList<String> city3 = new ArrayList<>();
city3.add("成都市");
city3.add("绵阳市");
city3.add("自贡市");
city3.add("攀枝花市");
city3.add("泸州市");
mapList.put("江苏省",city1);
mapList.put("湖北省",city2);
mapList.put("四川省",city3);
//遍历
Set<String> keys = mapList.keySet();
for(String k: keys){
//StringJoiner用于实现对字符串之间通过分隔符拼接的场景,第一个参数表示分隔符,第二个参数表示前缀,第三个参数表示后缀
StringJoiner sj = new StringJoiner(","," = ","");
//遍历市
for(String s:mapList.get(k)){
sj.add(s);
}
StringBuilder sb = new StringBuilder();
System.out.println(sb.append(k).append(sj).toString());
}
}