(五)集合与集合框架
11、Map实现类:
(1)HasgMap:
HashMap底层借助哈希表实现,元素的存取顺序不能保证一致。
HashMap存储的键值对时,如果键类型为自定义类,那么一般需要重写键所属类的hashCode()和equals()方法(重要,最常用)。
HashMap特点:
- 键唯一
- 值可重复
- 无序性
- 线程不安全
- 键和值的允许使用null【重点记忆】
public class Test083_HashMap {
public static void main(String[] args) {
//1.实例化HashMap对象,其中key类型为自定义Student
Map<Student, String> map = new HashMap<>();
//2.往集合中添加元素
// map中插入键值对,调用key所属类的hashCode和equals方法进行判断是否重复
map.put(new Student("zs", 78), "010");
map.put(new Student("rose", 82), "005");
map.put(new Student("lucy", 70), "009");
map.put(new Student("lucy", 70), "019"); //相同key,只能保留一项,"019"会覆盖"009"
map.put(new Student("ww", 67), "002");
//注意:HashMap中key和value都可以为null
map.put(new Student("tom", 86), null);
map.put(null, "002");
//3.基本方法测试
// 获取长度
System.out.println("size: " + map.size());
// 判断key是否存在
// 借助 key所属类的hashCode和equals方法完成
System.out.println("Student(ww,67)是否存在: " +
map.containsKey(new Student("ww", 67)));
// 判断value是否存在
// 借助value所属类型的 equals方法
System.out.println("是否存在 009: " +
map.containsValue("009"));
// 根据key删除,返回键对应的值
String value = map.remove(new Student("lucy", 70));
System.out.println("remove(Student(lucy, 70)): " + value);
System.out.println("---------------");
// 4.第一种遍历方法
Set<Student> keySet = map.keySet();
for (Student key : keySet) {
System.out.println(key + ": " + map.get(key));
}
System.out.println("---------------");
// 第二种方式遍历
Set<Entry<Student, String>> entrySet = map.entrySet();
for (Entry<Student, String> entry : entrySet) {
System.out.println(entry.getKey() + ": " +
entry.getValue());
}
}
}
//运行结果:
size: 6
Student(ww,67)是否存在: true
是否存在 009: false
remove(Student(lucy, 70)): 019
---------------
null: 002
Student [name=rose, age=82]: 005
Student [name=zs, age=78]: 010
Student [name=tom, age=86]: null
Student [name=ww, age=67]: 002
---------------
省略...
要注意,我在放代码时并没有导包,大家要注意,我主要是展示方法的用法与功能
(2)Hashtable:
Hashtable的特点:
- 键唯一
- 值可重复
- 无序性
- 线程安全,但性能不如HashMap,单线程用HashMap,多线程用Hashtable。
- 键和值都不允许使用null
- 底层是哈希表
案例展示:
public class Test084_Hashtable {
public static void main(String[] args) {
// 1.实例化HashMap对象,其中key类型为自定义Student
Hashtable<Student, String> map = new Hashtable<>();
// 2.往集合中添加元素
// map中插入键值对,调用key所属类的hashCode和equals方法进行判断是否重复
map.put(new Student("zs", 78), "010");
map.put(new Student("rose", 82), "005");
map.put(new Student("lucy", 70), "009");
map.put(new Student("lucy", 70), "019"); // 相同key,只能保留一项,"019"会覆盖"009"
map.put(new Student("ww", 67), "002");
// 注意:Hashtable中key和value不能为null,否则抛出NullPointerException
//map.put(new Student("tom", 86), null);
//map.put(null, "002");
// 3.遍历,Hashtable早期提供的方法较为繁琐
Enumeration<Student> keys = map.keys();
while(keys.hasMoreElements()) {
Student key = keys.nextElement();
String value = map.get(key);
System.out.println(key + ": " + value);
}
}
}
//运行输出:
Student [name=lucy, age=70]: 019
Student [name=zs, age=78]: 010
Student [name=ww, age=67]: 002
(3)TreeMap
TreeMap是Map接口的子类SortedMap的实现类
TreeMap的特点:
- 键唯一
- 值可重复
- 顺序可以按照自然排序或者比较器排序,比较器优先于自然排序
- 线程不安全
- key不能取null,value可以取null
- 底层是红黑树
注意:相比于HashMap等实现类,TreeMap在插入和删除操作上可能稍慢。因此,在选择使用TreeMap时,需要根据具体需求权衡性能和有序性的需求。
案例展示:一个比较器排序的例子
//注意导入自定义Student类
import com.briup.chap08.bean.Student;
//比较器排序
public static void main(String[] args) {
//1.额外提供比较器对象
Comparator<Student> comp = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//先按照名字降序
int r = o2.getName().compareTo(o1.getName());
//如果年龄一样,再按照年龄升序
if(r == 0)
r = o1.getAge() - o2.getAge();
return r;
}
};
//2.实例化TreeMap对象
Map<Student, String> map = new TreeMap<>(comp);
//3.添加键值对
map.put(new Student("zs", 78),"010");
map.put(new Student("rose", 82),"005");
map.put(new Student("lucy", 79),"009");
map.put(new Student("lucy", 79),"009");
map.put(new Student("tom", 68),"019");
map.put(new Student("tom", 86),"012");
map.put(new Student("ww", 67),"002");
//key不能为null,否则出 NullPointerException
//map.put(null,"002");
//4.遍历
Set<Entry<Student,String>> entrySet = map.entrySet();
for (Entry<Student, String> entry : entrySet) {
System.out.println(entry.getKey() + ": " +
entry.getValue());
}
}
//运行结果:
Student [name=zs, age=78]: 010
Student [name=ww, age=67]: 002
Student [name=tom, age=68]: 019
Student [name=tom, age=86]: 012
Student [name=rose, age=82]: 005
Student [name=lucy, age=79]: 009
(4)LinkedHashmap
LinkedHashMap的特点:
- 键唯一
- 值可重复
- 有序性,与插入顺序一致
- 线程不安全
- 键和值的允许使用null
- 底层是哈希表+链表
12、Collections工具类:
(1)概述:
属于util包,使用需要导包
类似于Array类,Collections类专门来操作集合对象,里面都是静态方法,可以直接调用。
Collections类无继承,无实现,父类为Object,私有构造器,只能通过类名调用方法与属性。
与Collection接口毫无关系
(2)方法:
1.
fill(List<? super T> list, T obj)
用法:将列表中所有元素替换为指定对象
obj
。参数:
list
:要填充的列表(必须是可修改的,否则抛UnsupportedOperationException
)。
obj
:用于替换列表元素的对象(可以为null
)。返回值:
void
(无返回值)。被调用者:
Collections
工具类(静态方法,直接通过类名调用)。示例:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c")); Collections.fill(list, "x"); // 列表变为 ["x", "x", "x"]
2.
max(Collection<? extends T> coll)
与max(Collection<? extends T> coll, Comparator<? super T> comp)
用法:返回集合中的最大元素。
参数:
coll
:要查找最大元素的集合(非空,否则抛NoSuchElementException
)。重载方法
max(Collection, Comparator)
:通过自定义比较器comp
定义排序规则。返回值:集合中的最大元素(类型为
T
)。要求:
无比较器的版本:集合元素必须实现
Comparable
接口(否则抛ClassCastException
)。有比较器的版本:通过比较器定义元素的大小关系。
示例:
List<Integer> nums = Arrays.asList(3, 1, 4); Integer max = Collections.max(nums); // 返回4(依赖Integer的自然排序) // 自定义比较器(字符串按长度排序) List<String> strs = Arrays.asList("apple", "cat", "banana"); String longest = Collections.max(strs, Comparator.comparingInt(String::length)); // longest = "banana"(长度最长)
3.
min(Collection<? extends T> coll)
与min(Collection<? extends T> coll, Comparator<? super T> comp)
用法:返回集合中的最小元素(与
max
逻辑对称)。参数:同
max
方法。返回值:集合中的最小元素(类型为
T
)。示例:
List<Integer> nums = Arrays.asList(3, 1, 4); Integer min = Collections.min(nums); // 返回1 List<String> strs = Arrays.asList("apple", "cat", "banana"); String shortest = Collections.min(strs, Comparator.comparingInt(String::length)); // shortest = "cat"(长度最短)
4.
reverse(List<?> list)
用法:反转列表中元素的顺序(第一个元素与最后一个交换,第二个与倒数第二个交换,以此类推)。
参数:
list
为要反转的列表(必须可修改)。返回值:
void
。示例:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); Collections.reverse(list); // 列表变为 [4, 3, 2, 1]
5.
sort(List<T> list)
与sort(List<T> list, Comparator<? super T> c)
用法:对列表进行排序(原地排序,修改原列表)。
参数:
list
:要排序的列表(必须可修改且支持随机访问,如 ArrayList;LinkedList 排序效率低)。重载方法
sort(List, Comparator)
:通过比较器c
定义排序规则。返回值:
void
。排序规则:
无比较器版本:元素需实现
Comparable
接口,按自然顺序排序。有比较器版本:按比较器定义的规则排序。
示例:
List<Integer> nums = new ArrayList<>(Arrays.asList(3, 1, 4)); Collections.sort(nums); // 自然排序,结果 [1, 3, 4] List<String> strs = new ArrayList<>(Arrays.asList("banana", "apple", "cat")); // 按字符串长度排序 Collections.sort(strs, Comparator.comparingInt(String::length)); // 结果 ["cat", "apple", "banana"]
6.
shuffle(List<?> list)
与shuffle(List<?> list, Random rnd)
用法:随机打乱列表中元素的顺序(基于随机数)。
参数:
list
:要打乱的列表(必须可修改)。重载方法
shuffle(List, Random)
:使用指定的随机数生成器rnd
,可控制随机性(如固定种子实现可重复的打乱结果)。返回值:
void
。示例:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); Collections.shuffle(list); // 随机打乱,结果可能为 [3, 1, 4, 2](每次不同) // 固定种子,打乱结果可重复 Random random = new Random(100); // 固定种子100 Collections.shuffle(list, random);
7.
addAll(Collection<? super T> c, T... elements)
用法:将多个元素批量添加到集合中(相当于多次调用
add
方法,但更高效)。参数:
c
:目标集合(必须支持add
操作,否则抛UnsupportedOperationException
)。
elements
:可变参数,要添加的元素(可为 0 个或多个)。返回值:
boolean
类型,true
表示集合因添加而发生改变(至少添加了一个元素)。示例:
List<String> list = new ArrayList<>(); // 添加多个元素 boolean changed = Collections.addAll(list, "a", "b", "c"); // list变为 ["a", "b", "c"],changed = true
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Test09_Collections {
public static void main(String[] args) {
//1.准备集合并添加元素
//List<Integer> list = Arrays.asList(5,3,4,2,2,7);
List<Integer> list = new ArrayList<>();
//addAll 往集合中添加多个元素
Collections.addAll(list,5,3,4,2,2,7);
System.out.println(list);
//2.max 获取最大值【默认采用自然排序】
Integer max = Collections.max(list);
System.out.println("max: " + max);
//3.min 获取集合最小值
Integer min = Collections.min(list);
System.out.println("min: " + min);
//4.reverse 反转
Collections.reverse(list);
System.out.println(list);
//4.sort 排序【按照 传入的排序算法 进行排序】
Comparator<Integer> comp = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 逆序
return o2-o1;
}
};
//注意:排序不会删除集合中的元素
Collections.sort(list,comp);
System.out.println("逆序: " + list);
//5.shuffle 随机打乱
Collections.shuffle(list);
System.out.println("打乱: " + list);
//6.sort 排序【默认自然排序】
Collections.sort(list);
System.out.println("自然排序: " + list);
//7.fill 填充
Collections.fill(list, 20);
System.out.println("after fill: " + list);
//8.将ArrayList【线程不安全】的集合 转换成 线程安全集合
//List<Integer> list2 = Collections.synchronizedList(list);
}
}