目录
前言
注:双列集合中各大类的成员方法跟单列集合几乎一致,若单列集合中成员方法掌握不熟,可以先看单列集合进阶那篇文章,再来学本篇章。
Map集合
概述和特点
-
Map集合概述
interface Map<K,V> K:键的类型;V:值的类型
-
Map集合的特点
- 双列集合,一个键对应一个值
- 键不可以重复,值可以重复
Map集合的基本使用
public class Main {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<>();
//V put(K key, V value) 将指定的值与该映射中的指定键相关联
map.put("fzx","qiqi");
map.put("zx","qixuan");
map.put("fz","xuanxuan");
map.put("fx","xiaoxuan");
//输出集合对象
System.out.println(map);//{fx=xiaoxuan, fz=xuanxuan, fzx=qiqi, zx=qixuan}
}
}
基本功能
方法介绍
方法名 | 说明 |
---|---|
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 V put(K key, V value)
返回值:V
存储键值对的时候,key不重复,返回值是null
存储键值对的时候,key重复,会使用新的value替换旧的value,返回旧的value(V)
public class myMapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//V put(K key,V value):添加元素
map.put("fzx","qiqi");
map.put("zx","qixuan");
map.put("fz","xuanxuan");
map.put("fx","xiaoxuan");
//V remove(Object key):根据键删除键值对元素
String v1 = map.remove("fx");
System.out.println(map);//{fz=xuanxuan, fzx=qiqi, zx=qixuan}
System.out.println(v1);//xiaoxuan
//boolean containsKey(Object key) 判断集合是否包含指定的键
System.out.println(map.containsKey("fx"));//false
System.out.println(map.containsKey("fz"));//true
//boolean containsValue(Object value) 判断集合是否包含指定的值
System.out.println(map.containsValue("qi"));//false
System.out.println(map.containsValue("qixuan"));//true
//boolean isEmpty():判断集合是否为空
System.out.println(map.isEmpty());//false
//int size():集合的长度,也就是集合中键值对的个数
System.out.println(map.size());//3
map.clear();
System.out.println(map);//{}
}
}
获取功能
-
方法介绍
方法名 说明 V get(Object key) 根据键获取值 Set<K> keySet() 获取所有键的集合 Collection<V> values() 获取所有值的集合 Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合 -
示例代码
public class Test {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//V put(K key,V value):添加元素
map.put("fzx","qiqi");
map.put("zx","qixuan");
map.put("fz","xuanxuan");
map.put("fx","xiaoxuan");
//V get(Object key):根据键获取值
String s1 = map.get("fzx");
System.out.println(s1);//qiqi
//Set<K> keySet() 获取所有键的集合
Set<String> key = map.keySet();
System.out.println(key);//[fx, fz, fzx, zx]
//Collection<V> values() 获取所有值的集合
Collection<String> values = map.values();
System.out.println(values);//[xiaoxuan, xuanxuan, qiqi, qixuan]
//Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合
Set<Map.Entry<String, String>> entries = map.entrySet();
System.out.println(entries);
//[fx=xiaoxuan, fz=xuanxuan, fzx=qiqi, zx=qixuan]
}
}
遍历方式1
-
遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
- 把所有的丈夫给集中起来
- 遍历丈夫的集合,获取到每一个丈夫
- 根据丈夫去找对应的妻子
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
-
步骤分析
- 获取所有键的集合。用keySet()方法实现
- 遍历键的集合,获取到每一个键。用增强for实现
- 根据键去找值。用get(Object key)方法实现
public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//添加元素
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
//获取所有键的集合。用keySet()方法实现
Set<String> keySet = map.keySet();
//Set<K> keySet():获取所有键的集合
for (String key : keySet) {
String value = map.get(key);
System.out.println(key+","+value);
}
}
}
遍历方式2
-
遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
- 获取所有结婚证的集合
- 遍历结婚证的集合,得到每一个结婚证
- 根据结婚证获取丈夫和妻子
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
-
步骤分析
- 获取所有键值对对象的集合
- Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 用增强for实现,得到每一个Map.Entry
- 根据键值对对象获取键和值
- 用getKey()得到键
- 用getValue()得到值
- 获取所有键值对对象的集合
-
代码实现
public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//添加元素
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
//获取所有键值对对象的集合
Set<Map.Entry<String, String>> entries = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<String, String> entry : entries) {
//根据键值对对象获取键和值
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+","+value);
}
}
}
HashMap集合
概述和特点
- HashMap底层是哈希表结构的
- 依赖hashCode方法和equals方法保证键的唯一
- 如果键要存储的是自定义对象,需要重写hashCode和equals方法
应用案例
-
案例需求
- 创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
- 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
-
代码实现
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student,String> hm = new HashMap<>();
//创建学生对象
Student s1 = new Student("林青霞", 30);
Student s2 = new Student("张曼玉", 35);
Student s3 = new Student("王祖贤", 33);
//重写hashCode的方法来去掉重复的键
Student s4 = new Student("王祖贤", 33);
//把学生添加到集合
hm.put(s1, "西安");
hm.put(s2, "武汉");
hm.put(s3, "郑州");
hm.put(s4, "北京");
Set<Student> keySet = hm.keySet();
for (Student key : keySet) {
String value = hm.get(key);
System.out.println(key+","+value);
}
}
}
class Student{
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
}
TreeMap集合
概述和特点
- TreeMap底层是红黑树结构
- 依赖自然排序或者比较器排序,对键进行排序
- 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
应用案例
-
案例需求
- 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
- 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
-
代码实现
public class Main {
public static void main(String[] args) {
// 创建TreeMap集合对象
TreeMap<Student,String> tm = new TreeMap<>();
Student s1 = new Student("xiaoxuan",25);
Student s2 = new Student("qixuan",25);
Student s3 = new Student("fzx",20);
tm.put(s1,"江苏");
tm.put(s2,"北京");
tm.put(s3,"天津");
tm.forEach((Student key, String value)->
System.out.println(key+","+value));
}
}
class Student implements Comparable<Student>{
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public int compareTo(Student o) {
//按照年龄进行排序
int temp = o.getAge() - this.age;
//次要条件,按照姓名排序。
temp = temp == 0 ? o.getName().compareTo(this.name) : temp;
return temp;
}
}
可变参数
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化.
格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
底层:
其实就是一个数组
好处:
在传递数据的时候,省的我们自己创建数组并添加元素了,JDK底层帮我们自动创建数组并添加元素了
public class VariadicParametersDemo {
public static void main(String[] args) {
int sum = sum(1,2,3,4,5,6,2023);
System.out.println(sum);//2044
}
public static int sum(int... arr){
int sum = 0;
for (int i : arr) {
sum = sum + i ;
}
return sum;
}
}
注意:
1.一个方法只能有一个可变参数
2.如果方法中有多个参数,可变参数要放到最后。
应用场景: Collections
在Collections中也提供了添加一些元素方法:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
//原来写法
//list.add(13);
//list.add(14);
//list.add(15);
//list.add(2023);
//采用工具类 完成 往集合中添加元素
Collections.addAll(list, 13, 14, 15,2023);
System.out.println(list);
}
Collections类
Collections常用功能
-
java.utils.Collections
是集合工具类,用来对集合进行操作。
常用方法如下
public static void shuffle(List<?> list):打乱集合顺序。
public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
代码演示:
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(300);
list.add(200);
list.add(500);
Collections.sort(list);
System.out.println(list);
//[100, 200, 300, 500]
}
}
Comparator比较器
创建一个学生类,存储到ArrayList集合中完成指定排序操作。
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("fzx",20));
list.add(new Student("qx",25));
list.add(new Student("qq",23));
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge() - o1.getAge();
}
});
System.out.println(list);
//[Student{name='qx', age=25}, Student{name='qq', age=23}, Student{name='fzx', age=20}]
}
}
class Student{
private String name;
private int age;
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
}
综合练习
练习1:随机点名器
需求:班级里有N个学生,实现随机点名器
public class Test1 {
public static void main(String[] args) {
//1.定义集合
ArrayList<String> list = new ArrayList<>();
//2.添加数据
Collections.addAll(list,"ff","zz","xx","qq","xuan","xiang");
//3.打乱集合
Collections.shuffle(list);
System.out.println(list.get(0));
}
}
练习2:带概率的随机
需求:
班级里有N个学生
要求在随机的时候,70%的概率随机到男生,30%的概率随机到女生
代码实现:
public class Test2 {
public static void main(String[] args) {
//创建两个集合分别存储男生和女生的名字
ArrayList<String> boyList = new ArrayList<>();
ArrayList<String> girlList = new ArrayList<>();
Collections.addAll(boyList,"m1","m2","m3","m4","m5","m6","m7","m8","m9");
Collections.addAll(girlList,"w1","w2","w3","w4","w5");
//随机整数范围为1-10
Random r = new Random();
int temp = r.nextInt(10)+1;
//随机数不大于7就是抽到男生的概率
if(temp<=7){
//打乱集合
Collections.shuffle(boyList);
System.out.println(boyList.get(0));
}else {
Collections.shuffle(girlList);
System.out.println(girlList.get(0));
}
}
}
练习3:随机不重复
需求:
班级里有N个学生,被点到的学生不会再被点到。但是如果班级中所有的学生都点完了, 需要重新开启第二轮点名。
代码实现:
public class Test3 {
public static void main(String[] args) {
/* 班级里有5个学生
要求:
被点到的学生不会再被点到。
但是如果班级中所有的学生都点完了,需要重新开启第二轮点名。*/
//1.定义集合
ArrayList<String> list = new ArrayList<>();
//创建一个临时的集合,用来存已经被点到学生的名字
ArrayList<String> newlist = new ArrayList<>();
//2.添加数据
Collections.addAll(list,"m1","m2","m3","w1","w2");
for (int j = 0; j < 5; j++) {
System.out.println("=========第" + j + "轮点名开始了======================");
//3.随机点名
Random r = new Random();
//4.获取集合的长度
int count = list.size();
for (int i = 0; i < count; i++) {
String s = list.remove(r.nextInt(list.size()));
System.out.println(s);
newlist.add(s);
}
list.addAll(newlist);
newlist.clear();
}
}
}
练习4:集合的嵌套
需求:
定义一个Map集合,键用表示省份名称province,值表示市city,但是市会有多个。
添加完毕后,遍历结果格式如下:
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
代码实现:
public class Test4 {
public static void main(String[] args) {
/* 需求
定义一个Map集合,键用表示省份名称province,值表示市city,但是市会有多个。
添加完毕后,遍历结果格式如下:
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
*/
HashMap<String, ArrayList<String>> hm = new HashMap<>();
ArrayList<String> city1 = new ArrayList<>();
ArrayList<String> city2 = new ArrayList<>();
ArrayList<String> city3 = new ArrayList<>();
Collections.addAll(city1,"南京市","扬州市","苏州市","无锡市","常州市");
Collections.addAll(city2,"武汉市","孝感市","十堰市","宜昌市","鄂州市");
Collections.addAll(city3,"石家庄市","唐山市","邢台市","保定市","张家口市");
hm.put("江苏省",city1);
hm.put("湖北省",city2);
hm.put("河北省",city3);
Set<Map.Entry<String, ArrayList<String>>> entries = hm.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
//entry依次表示每一个键值对对象
String key = entry.getKey();
ArrayList<String> value = entry.getValue();
System.out.println(key+"="+value);
}
}
}