📃个人主页:个人主页
🔥系列专栏:JAVASE基础
目录
一、Set系列集合
1.HashSet
2.LinkedHashSet
3.TreeSet
二、补充知识
1.可变参数
2.集合工具类Collections
三、Map集合体系
1.Map集合的概述
2.Map集合体系特点
3.Map集合常用API
4.Map集合的遍历方式
1.Map集合的遍历方式一:键找值
2.Map集合的遍历方式二:键值对
3.Map集合的遍历方式三:Lambda
5.Map集合的实现类HashMap
6.Map集合的实现类LinkedHashMap
7.Map集合的实现类TreeMap
一、Set系列集合
Set系列集合特点
- 无序:存取顺序不一致
- 不重复:可以去除重复
- 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。
Set集合实现类特点
- HashSet : 无序、不重复、无索引。
- LinkedHashSet:有序、不重复、无索引。
- TreeSet:可排序、不重复、无索引。
1.HashSet
- HashSet集合底层采取哈希表存储的数据。
- 哈希表是一种对于增删改查数据性能都较好的结构。
HashSet底层原理
- HashSet集合底层采取哈希表存储的数据。
- 哈希表是一种对于增删改查数据性能都较好的结构。
哈希表的组成
- JDK8之前的,底层使用数组+链表组成
- JDK8开始后,底层采用数组+链表+红黑树组成。
在了解哈希表之前需要先理解哈希值的概念
哈希值
是JDK根据对象的地址,按照某种规则算出来的int类型的数值。
Object类的API
public int hashCode():返回对象的哈希值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。
public class Main {
public static void main(String[] args) {
String str="123";
System.out.println(str.hashCode());
System.out.println(str.hashCode());
String str2="1234";
System.out.println(str2.hashCode());
System.out.println(str2.hashCode());
}
}
2.LinkedHashSet
- 有序、不重复、无索引。
- 这里的有序指的是保证存储和取出的元素顺序一致
- 原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
3.TreeSet
- 不重复、无索引、可排序
- 可排序:按照元素的大小默认升序(有小到大)排序。
- TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
- 注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。
TreeSet集合默认的规则
- 对于数值类型:Integer , Double,官方默认按照大小进行升序排序。
- 对于字符串类型:默认按照首字符的编号升序排序。
- 对于自定义类型如Student对象,TreeSet无法直接排序。
自定义排序规则
TreeSet集合存储对象的的时候有2种方式可以设计自定义比较规则
- 方式一 让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
- 方式二 TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。
1. 如果希望元素可以重复,又有索引,索引查询要快?
用ArrayList集合,基于数组的。(用的最多)
2. 如果希望元素可以重复,又有索引,增删首尾操作快?
用LinkedList集合,基于链表的。
3. 如果希望增删改查都快,但是元素不重复、无序、无索引。
用HashSet集合,基于哈希表的。
4. 如果希望增删改查都快,但是元素不重复、有序、无索引。
用LinkedHashSet集合,基于哈希表和双链表。
5. 如果要对对象进行排序。
用TreeSet集合,基于红黑树。后续也可以用List集合实现排序。
二、补充知识
1.可变参数
可变参数
- 可变参数用在形参中可以接收多个数据。
- 可变参数的格式:数据类型...参数名称
可变参数的作用
- 接收参数非常灵活,方便。可以不接收参数,可以接收1个或者多个参数,也可以接收一个数组
- 可变参数在方法内部本质上就是一个数组。
可变参数的注意事项:
1.一个形参列表中可变参数只能有一个
2.可变参数必须放在形参列表的最后面
public class Test {
public static void main(String[] args) {
test(0);
System.out.println("---------------------");
test(1,2);
System.out.println("---------------------");
test(1,3,5,7);
}
public static void test(int... num) {
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
}
}
2.集合工具类Collections
Collections集合工具类
- java.utils.Collections:是集合工具类
- 作用:Collections并不属于集合,是用来操作集合的工具类。
Collections常用的API
方法名称 | 说明 |
public static <T> boolean addAll(Collection<? super T> c, T... elements) | 给集合对象批量添加元素 |
public static void shuffle(List<?> list) | 打乱List集合元素的顺序 |
Collections排序相关API
使用范围:只能对于List集合的排序。
排序方式1:
方法名称 | 说明 |
public static <T> void sort(List<T> list) | 将集合中元素按照默认规则排序 |
注意:本方式不可以直接对自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable接口。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"98","5","2","7","3","1");
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
排序方式2:
方法名称 | 说明 |
public static <T> void sort(List<T> list,Comparator<? super T> c) | 将集合中元素按照指定规则排序 |
三、Map集合体系
1.Map集合的概述
Map集合概述和使用
- Map集合是一种双列集合,每个元素包含两个数据。
- Map集合的每个元素的格式:key=value(键值对元素)。
- Map集合也被称为“键值对集合”。
Map集合整体格式:
- Collection集合的格式: [元素1,元素2,元素3..]
- Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}
2.Map集合体系特点
Map集合体系
说明
- 使用最多的Map集合是HashMap。
- 重点掌握HashMap , LinkedHashMap , TreeMap。其他的后续理解。
Map集合体系特点
- Map集合的特点都是由键决定的。
- Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)。
- Map集合后面重复的键对应的值会覆盖前面重复键的值。
- Map集合的键值对都可以为null。
Map集合实现类特点
- HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)
- LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
- TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
3.Map集合常用API
Map集合
- Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。
Map API如下:
方法名称 | 说明 |
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
public class Test {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//1.V put(K key,V value) 添加元素
map.put("java",1);
map.put("html",12);
map.put("css",21);
map.put("rust",3);
map.put("js",9);
System.out.println(map);
System.out.println("-------------------------");
//2.V remove(Object key) 根据键删除键值对元素
map.remove("java");
System.out.println(map);
System.out.println("-------------------------");
//3.void clear() 移除所有的键值对元素
// map.clear();
// System.out.println(map);
// System.out.println("-------------------------");
//4. boolean containsKey(Object key) 判断集合是否包含指定的键
System.out.println(map.containsKey("java"));
System.out.println(map.containsKey("js"));
System.out.println("-------------------------");
//5.boolean containsValue(Object value) 判断集合是否包含指定的值
System.out.println(map.containsValue(12));
System.out.println("-------------------------");
//6. boolean isEmpty() 判断集合是否为空
System.out.println(map.isEmpty());
System.out.println("-------------------------");
//7. int size() 集合的长度,也就是集合中键值对的个数
System.out.println(map.size());
}
}
4.Map集合的遍历方式
Map集合的遍历方式有:3种。
- 方式一:键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。
- 方式二:键值对的方式遍历,把“键值对“看成一个整体,难度较大。
- 方式三:JDK 1.8开始之后的新技术:Lambda表达式。
1.Map集合的遍历方式一:键找值
- 先获取Map集合的全部键的Set集合。
- 遍历键的Set集合,然后通过键提取对应值。
键找值涉及到的API:
方法名称 | 说明 |
Set<K> keySet() | 获取所有键的集合 |
V get(Object key) | 根据键获取值 |
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//1.V put(K key,V value) 添加元素
map.put("java",1);
map.put("html",12);
map.put("css",21);
map.put("rust",3);
map.put("js",9);
System.out.println(map);
Set<String> keys = map.keySet();
for (String key : keys) {
Integer value = map.get(key);
System.out.println(key+"----->"+value);
}
}
2.Map集合的遍历方式二:键值对
- 先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了。
- 遍历Set集合,然后提取键以及提取值。
键值对涉及到的API:
方法名称 | 说明 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
K getKey() | 获得键 |
V getValue() | 获取值 |
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//1.V put(K key,V value) 添加元素
map.put("java", 1);
map.put("html", 12);
map.put("css", 21);
map.put("rust", 3);
map.put("js", 9);
System.out.println(map);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"----->"+value);
}
}
}
3.Map集合的遍历方式三:Lambda
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
Map结合Lambda遍历的API
方法名称 | 说明 |
default void forEach(BiConsumer<? super K, ? super V> action) | 结合lambda遍历Map集合 |
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//1.V put(K key,V value) 添加元素
map.put("java", 1);
map.put("html", 12);
map.put("css", 21);
map.put("rust", 3);
map.put("js", 9);
System.out.println(map);
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String key, Integer value) {
System.out.println(key+"----->"+value);
}
});
}
}
代码简化一下:
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//1.V put(K key,V value) 添加元素
map.put("java", 1);
map.put("html", 12);
map.put("css", 21);
map.put("rust", 3);
map.put("js", 9);
System.out.println(map);
map.forEach( (key, value) ->{
System.out.println(key+"----->"+value);
});
}
}
5.Map集合的实现类HashMap
说明
- 使用最多的Map集合是HashMap。
- 重点掌握HashMap , LinkedHashMap , TreeMap。其他的后续理解。
HashMap的特点
- HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
- 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
- HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。
实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
HashMap 是 Java 中的一个集合类,它用来存储键值对。它实现了 Map 接口,可以存储不同类型的键和值,并且允许 null 值。在 HashMap 中,键是唯一的,值可以重复。
HashMap 中最常用的方法包括:
- put(key, value):将键值对添加到 HashMap 中。
- get(key):获取指定键对应的值。
- remove(key):删除指定键对应的键值对。
- containsKey(key):判断 HashMap 是否包含指定的键。
- keySet():返回 HashMap 中所有键组成的 Set 集合。
public static void main(String[] args) {
// 创建一个名为capitalCities的HashMap对象
HashMap<String, String> capitalCities = new HashMap<String, String>();
// 添加键和值(国家,城市)
capitalCities.put("England", "London");
capitalCities.put("Germany", "Berlin");
capitalCities.put("Norway", "Oslo");
capitalCities.put("USA", "Washington DC");
// 通过使用键访问值
System.out.println("英格兰的首都是 " + capitalCities.get("England"));
// 删除一个键和值
capitalCities.remove("Norway");
// 打印键
System.out.println("键: " + capitalCities.keySet());
// 检查一个键是否在HashMap中
System.out.println("capitalCities是否包含Norway作为键? " + capitalCities.containsKey("Norway"));
}
英格兰的首都是 London
键: [USA, England, Germany]
capitalCities是否包含Norway作为键? false
6.Map集合的实现类LinkedHashMap
LinkedHashMap是Java集合框架中的一种Map实现,它继承自 HashMap 类,底层使用双向链表维护元素的顺序。特点是能够保持插入顺序,即遍历顺序与插入顺序相同,同时也支持按照访问顺序排序,即根据元素最近被访问的时间排序。其键值对是唯一的,键和值都可以为null。 对于访问顺序,可以通过构造函数或调用 afterNodeAccess、beforeNodeInsertion 等访问方法来配置。此外,LinkedHashMap 还实现了 removeEldestEntry 方法,它的作用是当元素个数超过指定阈值时,删除最不常访问的元素。
LinkedHashMap类实现了Map接口,使用双向链表维护插入顺序。具有如下主要方法:
- void clear():从此映射中删除所有映射关系。
- boolean containsKey(Object key):如果此映射包含指定键的映射关系,则返回true。
- boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回true。
- Set<Entry<K,V>> entrySet():返回此映射中所包含的映射关系的Set视图。
- V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null。
- boolean isEmpty():如果此映射未包含键-值映射关系,则返回true。
- Set<K> keySet():返回此映射中包含的键的Set视图。
- V put(K key, V value):将指定的值与此映射中的指定键关联。
- void putAll(Map<? extends K,? extends V> m):将指定映射中的所有映射关系复制到此映射中。
- V remove(Object key):从此映射中移除指定键的映射关系(如果存在)。
- int size():返回此映射中的键-值映射关系数。
- Collection<V> values():返回此映射中包含的值的Collection视图。
注意:LinkedHashMap是非线程安全的。
LinkedHashMap集合可以保持插入顺序,如果已经存在的键再次被放入,那么会把原来对应的值覆盖掉。以下是一个简单的例子:
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>(); // 创建 LinkedHashMap 对象
map.put("apple", 1); // 插入数据
map.put("banana", 2);
map.put("orange", 3);
map.put("apple", 4); // 覆盖相同键的值
for (Map.Entry<String, Integer> entry : map.entrySet()) { // 遍历输出
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
apple: 4
banana: 2
orange: 3
7.Map集合的实现类TreeMap
TreeMap 是 Java 中的一种有序的数据结构,基于红黑树实现,可以根据键值进行排序。TreeMap 中存储的元素都是键值对(key-value),其中键是唯一的。
TreeMap集合概述和特点:
- 由键决定特性:不重复、无索引、可排序
- 可排序:按照键数据的大小默认升序(有小到大)排序。只能对键排序。
- 注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序
- TreeMap跟TreeSet一样底层原理是一样的。
TreeMap集合自定义排序规则有2种
- 类实现Comparable接口,重写比较规则。
- 集合自定义Comparator比较器对象,重写比较规则。
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
// 创建一个TreeMap对象,指定键的类型为String,值的类型为Integer
TreeMap<String, Integer> map = new TreeMap<>();
// put()方法向TreeMap中添加元素
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
// 通过遍历TreeMap来获取元素
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
}
}