[0开始学Java|第二十四天]集合(Map&可变参数&集合工具类Collections)
本文摘要主要介绍Java中Map集合及其常见实现类的特点和使用方法。主要内容包括: Map集合的特点和常用API,如put()、remove()、containsKey()等 Map的三种遍历方式:键找值、键值对和Lambda表达式 HashMap的特点、底层原理和使用案例(存储自定义对象和统计功能) LinkedHashMap的有序特性 TreeMap的排序功能,包括自然排序和自定义排序 Col
·
双列集合的特点



Map的常见API

例如:
(源代码)
package com.itheima.a01mymap;
import java.util.HashMap;
import java.util.Map;
public class A01_MapDemo1 {
public static void main(String[] args) {
/*
V put(K key,V value) 添加元素
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数
*/
//1.创建Map集合的对象
Map<String, String> m = new HashMap<>();
//2.添加元素
//put方法的细节:
//添加/覆盖
//在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
//在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
m.put("郭靖", "黄蓉");
m.put("韦小宝","沐剑屏");
m.put("尹志平","小龙女");
//System.out.println(m);//{韦小宝=沐剑屏, 尹志平=小龙女, 郭靖=黄蓉}
String value2 = m.put("韦小宝", "双儿");
System.out.println(value2);//沐剑屏
//System.out.println(m);//{韦小宝=双儿, 尹志平=小龙女, 郭靖=黄蓉}
//3.删除
//String result = m.remove("郭靖");
//System.out.println(result);//黄蓉
//4.清空
//m.clear();
//5.判断是否包含
/*
boolean keyResult = m.containsKey("郭靖");
System.out.println(keyResult);//true
boolean valueResult = m.containsValue("小龙女2");
System.out.println(valueResult);//false
*/
//6.判断集合是否为空
/*
boolean result = m.isEmpty();
System.out.println(result);//false
*/
//7.集合的长度,也就是集合中键值对的个数
int size = m.size();
System.out.println(size);
//8.打印集合
System.out.println(m);//{韦小宝=双儿, 尹志平=小龙女, 郭靖=黄蓉}
}
}
(运行结果截图)

Map集合的遍历方式

Map集合的第一种遍历方式(键找值)
第一步:把所有的键都获取出来,放在一个单列集合当中;
第二步:遍历单列集合,得到里面的每一个键;
第三步:通过get方法依次获取每一个键所对应的值。

例如:
(源代码)
package com.itheima.a01mymap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import java.util.function.Consumer;
public class A02_MapDemo2 {
public static void main(String[] args) {
//Map集合的第一种遍历方式
//三个课堂练习:
//
//练习一: 利用键找值的方式遍历map集合,要求:装着键的单列集合使用增强for的形式进行遍历
//练习二: 利用键找值的方式遍历map集合,要求:装着键的单列集合使用迭代器的形式进行遍历
//练习三: 利用键找值的方式遍历map集合,要求:装着键的单列集合使用lambda表达式的形式进行遍历
//1.创建Map集合的对象
Map<String,String> map = new HashMap<>();
//2.添加元素
map.put("尹志平","小龙女");
map.put("郭靖","穆念慈");
map.put("欧阳克","黄蓉");
//3.通过键找值
//获取所有的键,把这些键放到一个单列集合当中
Set<String> keys = map.keySet();
//练习一:
//遍历单列集合,得到每一个键
for (String key : keys) {
//System.out.println(key);
//3.3 利用map集合中的键获取对应的值 get
String value = map.get(key);
System.out.println(key + " = " + value);
}
//练习二:
System.out.println("-------------------");
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String key = it.next();
String value = map.get(key);
System.out.println(key + " = " + value);
}
//练习三:
System.out.println("-------------------");
keys.forEach(new Consumer<String>() {
@Override
public void accept(String key) {
String value = map.get(key);
System.out.println(key + " = " + value);
}
});
}
}
(运行结果截图)

Map集合的第二种遍历方式(键值对)
依次获取里面的每一对键值对对象,再通过getKey()方法获取里面的键,通过getValue()方法获取里面的值,重复操作直至将所有数据都遍历出来


例如:
(源代码)
package com.itheima.a01mymap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class A03_MapDemo3 {
public static void main(String[] args) {
//Map集合的第二种遍历方式
//三个课堂练习:
//
//练习一: 通过键值对对象进行遍历map集合,要求:装着键值对对象的单列集合使用增强for的形式进行遍历
//练习二: 通过键值对对象进行遍历map集合,要求:装着键值对对象的单列集合使用迭代器的形式进行遍历
//练习三: 通过键值对对象进行遍历map集合,要求:装着键值对对象的单列集合使用lambda的形式进行遍历
//1.创建Map集合的对象
Map<String, String> map = new HashMap<>();
//2.添加元素
//键:人物的外号
//值:人物的名字
map.put("标枪选手", "马超");
map.put("人物挂件", "明世隐");
map.put("御龙骑士", "尹志平");
//3.Map集合的第二种遍历方式
//通过键值对对象进行遍历
//通过一个方法获取所有的键值对对象,返回一个Set集合
Set<Map.Entry<String, String>> entries = map.entrySet();
//练习一:
//遍历entries这个集合,去得到里面的每一个键值对对象
for (Map.Entry<String, String> entry : entries) {//entry ---> "御龙骑士","尹志平"
//3.3 利用entry调用get方法获取键和值
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
(运行结果截图)

Map集合的第三种遍历方式(Lambda表达式)

例如:
(源代码)
package com.itheima.a01mymap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class A04_MapDemo4 {
public static void main(String[] args) {
//Map集合的第三种遍历方式
//1.创建Map集合的对象
Map<String,String> map = new HashMap<>();
//2.添加元素
//键:人物的名字
//值:名人名言
map.put("鲁迅","这句话是我说的");
map.put("曹操","不可能绝对不可能");
map.put("刘备","接着奏乐接着舞");
map.put("柯镇恶","看我眼色行事");
//3.利用lambda表达式进行遍历
//底层:
//forEach其实就是利用第二种方式进行遍历,依次得到每一个键和值
//再调用accept方法
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
System.out.println(key + "=" + value);
}
});
System.out.println("-----------------------------------");
map.forEach((String key, String value)->{
System.out.println(key + "=" + value);
}
);
System.out.println("-----------------------------------");
map.forEach((key, value)-> System.out.println(key + "=" + value));
}
}
(运行结果截图)

HashMap
HashMap的基本使用
HashMap的特点

HashMap的底层原理


总结

HashMap练习一(存储自定义对象)
案例:存储学生对象并遍历

(源代码)
[A01_HashMapDemo1]
package com.itheima.a02myhashmap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class A01_HashMapDemo1 {
public static void main(String[] args) {
/*
需求:创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。
存储三个键值对元素,并遍历
要求:同姓名,同年龄认为是同一个学生
核心点:
HashMap的键位置如果存储的是自定义对象,需要重写hashCode和equals方法。
*/
//1.创建HashMap的对象
HashMap<Student,String> hm = new HashMap<>();
//2.创建三个学生对象
Student s1 = new Student("zhangsan",23);
Student s2 = new Student("lisi",24);
Student s3 = new Student("wangwu",25);
Student s4 = new Student("wangwu",25);
//3.添加元素
hm.put(s1,"江苏");
hm.put(s2,"浙江");
hm.put(s3,"福建");
hm.put(s4,"山东");
//4.遍历集合
//键找值
Set<Student> keys = hm.keySet();
for (Student key : keys) {
String value = hm.get(key);
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
//键值对
Set<Map.Entry<Student, String>> entries = hm.entrySet();
for (Map.Entry<Student, String> entry : entries) {
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
System.out.println("--------------------------");
//Lambda表达式
hm.forEach((student, s)-> System.out.println(student + "=" + s));
}
}
[Student]
package com.itheima.a02myhashmap;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = 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);
return name.hashCode();
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
(运行结果截图)

HashMap练习二(利用Map集合进行统计)
案例:Map集合案例-统计投票人数

(分析)

(源代码)
package com.itheima.a02myhashmap;
import java.util.*;
public class A02_HashMapDemo2 {
public static void main(String[] args) {
/*
某个班级80名学生,现在需要组成秋游活动,
班长提供了四个景点依次是(A、B、C、D),
每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。
*/
//1.需要先让同学们投票
//定义一个数组,存储4个景点
String[] arr = {"A","B","C","D"};
//利用随机数模拟80个同学的投票,并把投票的结果存储起来
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 80; i++) {
int index = r.nextInt(arr.length);
list.add(arr[index]);
}
//2.如果要统计的东西比较多,不方便使用计数器思想
//我们可以定义map集合,利用集合进行统计。
HashMap<String,Integer> hm = new HashMap<>();
for (String name : list) {
//判断当前的景点在map集合当中是否存在
if(hm.containsKey(name)){
//存在
//先获取当前景点已经被投票的次数
int count = hm.get(name);
//表示当前景点又被投了一次
count++;
//把新的次数再次添加到集合当中
hm.put(name,count);
}else{
//不存在
hm.put(name,1);
}
}
System.out.println(hm);//{A=19, B=25, C=17, D=19}
//3.求最大值
int max = 0;
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
int count = entry.getValue();
if(count > max){
max = count;
}
}
System.out.println(max);//25
//4.判断哪个景点的次数跟最大值一样,如果一样,打印出来
for (Map.Entry<String, Integer> entry : entries) {
int count = entry.getValue();
if(count == max){
System.out.println(entry.getKey());//B
}
}
}
}
(运行结果截图)

LinkedHashMap

LinkedHashMap的特点


package com.itheima.a03mylinkedhashmap;
import java.util.LinkedHashMap;
public class A01_LinkedHashMapDemo1 {
public static void main(String[] args) {
/*
LinkedHashMap:
由键决定:
有序、不重复、无索引。
有序:
保证存储和取出的顺序一致
原理:
底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
*/
//1.创建集合
LinkedHashMap<String,Integer> lhm = new LinkedHashMap<>();
//2.添加元素
lhm.put("c",789);
lhm.put("b",456);
lhm.put("a",123);
lhm.put("a",111);
//3.打印集合
System.out.println(lhm);
}
}
TreeMap
TreeMap的基本使用
TreeMap的特点

代码书写两种排序规则

TreeMap的基本应用

需求1:
升序
(源代码)
package com.itheima.a04mytreemaptest;
import java.util.TreeMap;
public class a01_TreeMapDemo1 {
public static void main(String[] args) {
/*
TreeMap集合:基本应用
需求1:
键:整数表示id
值:字符串表示商品名称
要求1:按照id的升序排列
要求2:按照id的降序排列
*/
TreeMap<Integer,String> tm = new TreeMap<>();
tm.put(1001, "手机");
tm.put(1004, "电脑");
tm.put(1005, "电视");
tm.put(1002, "手表");
tm.put(1003, "耳机");
System.out.println(tm);
}
}
(运行结果截图)

降序
(源代码)
package com.itheima.a04mytreemaptest;
import java.util.Comparator;
import java.util.TreeMap;
public class a01_TreeMapDemo2 {
public static void main(String[] args) {
/*
TreeMap集合:基本应用
需求1:
键:整数表示id
值:字符串表示商品名称
要求1:按照id的升序排列
要求2:按照id的降序排列
*/
TreeMap<Integer,String> tm = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//o1:当前要添加的元素
//o2:表示已经在红黑树中存在的元素
return o2 - o1;
}
});
tm.put(1001, "手机");
tm.put(1004, "电脑");
tm.put(1005, "电视");
tm.put(1002, "手表");
tm.put(1003, "耳机");
System.out.println(tm);
}
}
(运行结果截图)
需求2:
(源代码)
package com.itheima.a04mytreemaptest;
import java.util.Comparator;
import java.util.TreeMap;
public class a01_TreeMapDemo3 {
public static void main(String[] args) {
/*
TreeMap集合:基本应用
需求2:
键:学生对象
值:籍贯
要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人。
*/
Student stu1 = new Student("zhangsan", 18);
Student stu2 = new Student("lisi", 20);
Student stu3 = new Student("wangwu", 19);
TreeMap<Student,String> m = new TreeMap<>();
m.put(stu1, "天津");
m.put(stu2, "上海");
m.put(stu3, "北京");
System.out.println(m);
}
}
(运行结果截图)

案例:统计个数

(源代码)
package com.itheima.a04mytreemaptest;
import java.util.StringJoiner;
import java.util.TreeMap;
public class a01_TreeMapDemo4 {
public static void main(String[] args) {
/* 需求:
字符串“aababcabcdabcde”
请统计字符串中每一个字符出现的次数,并按照以下格式输出
输出结果:
a(5)b(4)c(3)d(2)e(1)
新的统计思想:利用map集合进行统计
如果题目中没有要求对结果进行排序,默认使用HashMap
如果题目中要求对结果进行排序,请使用TreeMap
键:表示要统计的内容
值:表示次数
*/
String s = "aababcabcdabcde";
TreeMap<Character,Integer> tm = new TreeMap<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(tm.containsKey(c)){
//存在
int count = tm.get(c);
count++;
tm.put(c,count);
}else{
//不存在
tm.put(c,1);
}
}
StringBuilder sb = new StringBuilder();
tm.forEach((k,v)-> sb.append(k).append("(").append(v).append(")"));
System.out.println(sb);
System.out.println("-----------------------------");
StringJoiner sj = new StringJoiner("","","");
tm.forEach((key, v) -> sj.add(key + "").add("(").add(v + "").add(")"));
System.out.println(sj);
}
}
(运行结果截图)

总结

可变参数
案例:可变参数的练习

(源代码)
package com.itheima.a06myargstest;
public class a01_MyArgsTestDemo1 {
public static void main(String[] args) {
//JDK5
//可变参数
//方法形参的个数是可以发生变化的,0 1 2 3 ...
//格式:属性类型...名字
//int...args
int sum = getSum(1,2,3,4,5,6,7,8,9);
System.out.println(sum);
}
//底层:
//可变参数底层就是一个数组
//只不过不需要我们自己创建了,Java会帮我们创建好
public static int getSum(int... args) {
//System.out.println(args);//[I@119d7047
int sum = 0;
for(int i : args){
sum = sum + i;
}
return sum;
}
}
(运行结果截图)

可变参数的小细节:
1.在方法的形参中最多只能写一个可变参数
可变参数,理解为一个大胖子,有多少吃多少
2.在方法的形参当中,如果出了可变参数以外,还有其他的形参,那么可变参数要写在最后
例如:
总结

Collections
什么是Collections?

Collections常用的API

例1:
(源代码)
package com.itheima.a07mycollections;
import java.util.ArrayList;
import java.util.Collections;
public class CollectionsDemo1 {
public static void main(String[] args) {
/*
public static <T> boolean addAll(Collection<T> c, T... elements) 批量添加元素
public static void shuffle(List<?> list) 打乱List集合元素的顺序
*/
//addAll 批量添加元素
//1.创建集合对象
ArrayList<String> list = new ArrayList<>();
//2.批量添加元素
Collections.addAll(list,"abc","bcd","qwer","df","asdf","zxcv","1234","qwer");
//3.打印集合
System.out.println(list);//[abc, bcd, qwer, df, asdf, zxcv, 1234, qwer]
//shuffle 打乱
Collections.shuffle(list);
System.out.println(list);
}
}
(运行结果截图)

例2:
(源代码)
package com.itheima.a07mycollections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class CollectionsDemo2 {
public static void main(String[] args) {
/*
public static <T> void sort(List<T> list) 排序
public static <T> void sort(List<T> list, Comparator<T> c) 根据指定的规则进行排序
public static <T> int binarySearch (List<T> list, T key) 以二分查找法查找元素
public static <T> void copy(List<T> dest, List<T> src) 拷贝集合中的元素
public static <T> int fill (List<T> list, T obj) 使用指定的元素填充集合
public static <T> void max/min(Collection<T> coll) 根据默认的自然排序获取最大/小值
public static <T> void swap(List<?> list, int i, int j) 交换集合中指定位置的元素
*/
System.out.println("-------------sort默认规则--------------------------");
//默认规则,需要重写Comparable接口compareTo方法。Integer已经实现,按照从小打大的顺序排列
//如果是自定义对象,需要自己指定规则
ArrayList<Integer> list1 = new ArrayList<>();
Collections.addAll(list1, 10, 1, 2, 4, 8, 5, 9, 6, 7, 3);
Collections.sort(list1);
System.out.println(list1);
System.out.println("-------------sort自己指定规则规则--------------------------");
Collections.sort(list1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(list1);
Collections.sort(list1, (o1, o2) -> o2 - o1);
System.out.println(list1);
System.out.println("-------------binarySearch--------------------------");
//需要元素有序
ArrayList<Integer> list2 = new ArrayList<>();
Collections.addAll(list2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(Collections.binarySearch(list2, 9));
System.out.println(Collections.binarySearch(list2, 1));
System.out.println(Collections.binarySearch(list2, 20));
System.out.println("-------------copy--------------------------");
//把list3中的元素拷贝到list4中
//会覆盖原来的元素
//注意点:如果list3的长度 > list4的长度,方法会报错
ArrayList<Integer> list3 = new ArrayList<>();
ArrayList<Integer> list4 = new ArrayList<>();
Collections.addAll(list3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Collections.addAll(list4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
Collections.copy(list4, list3);
System.out.println(list3);
System.out.println(list4);
System.out.println("-------------fill--------------------------");
//把集合中现有的所有数据,都修改为指定数据
ArrayList<Integer> list5 = new ArrayList<>();
Collections.addAll(list5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Collections.fill(list5, 100);
System.out.println(list5);
System.out.println("-------------max/min--------------------------");
//求最大值或者最小值
ArrayList<Integer> list6 = new ArrayList<>();
Collections.addAll(list6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(Collections.max(list6));
System.out.println(Collections.min(list6));
System.out.println("-------------max/min指定规则--------------------------");
// String中默认是按照字母的abcdefg顺序进行排列的
// 现在我要求最长的字符串
// 默认的规则无法满足,可以自己指定规则
// 求指定规则的最大值或者最小值
ArrayList<String> list7 = new ArrayList<>();
Collections.addAll(list7, "a","aa","aaa","aaaa");
System.out.println(Collections.max(list7, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}));
System.out.println("-------------swap--------------------------");
ArrayList<Integer> list8 = new ArrayList<>();
Collections.addAll(list8, 1, 2, 3);
Collections.swap(list8,0,2);
System.out.println(list8);
}
}
(运行结果截图)

更多推荐




所有评论(0)