目录
双列集合
双列集合的特点
集合体系结构
Map的常见API
Map的遍历方式
键找值
键值对
Lambda表达式
底层源码:
HashMap
HashMap的特点
案例
LinkedHashMap
TreeMap
TreeMap基本应用
需求1:
需求2:
案例
可变参数
Collections
Collections常用的API
案例
自动点名器1
自动点名器2
① 双列集合一次需要存一对数据,分别为键和值
② 键不能重复,值可以重复
③ 键和值是一一对应的,每一个键只能找到自己对应的值
④ 键+值这个整体,我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”
Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
方法名称 | 说明 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
put方法的细节:
含义:添加/覆盖
在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回nu11
在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
package mymap;
import java.util.HashMap;
import java.util.Map;
/**
* | 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 MapDemo1 {
public static void main(String[] args) {
//创建集合对象
Map map = new HashMap<>();
//添加元素
map.put("AAA","aaa");
map.put("BBB","bbb");
map.put("CCC","ccc");
//打印集合
System.out.println(map); //{AAA=aaa, CCC=ccc, BBB=bbb}
System.out.println("----------------------------------------");
//根据键删除键值对元素
String result = map.remove("AAA");
//打印被删除的值
System.out.println(result); //aaa
//打印集合
System.out.println(map); //{AAA=aaa, CCC=ccc, BBB=bbb}
System.out.println("----------------------------------------");
//判断集合是否包含指定的键
boolean keyResult = map.containsKey("BBB"); //true
System.out.println(keyResult);
System.out.println("----------------------------------------");
//判断集合是否包含指定的值
boolean valueResult = map.containsValue("bbb");
System.out.println(valueResult); //true
System.out.println("----------------------------------------");
//移除所有的键值对元素
map.clear();
//打印集合
System.out.println(map); //{}
//判断集合是否为空
boolean empty = map.isEmpty();
System.out.println(empty); //true
//集合的长度,也就是集合中键值对的个数
int size = map.size();
System.out.println(size); //0
}
}
获取所有的键,并把这些键放到一个单列集合中,遍历单列集合,得到每一个键,利用map集合中的键获取对应的值
public class MapDemo2 {
public static void main(String[] args) {
//创建集合对象
Map map = new HashMap<>();
//添加元素
map.put("AAA", "aaa");
map.put("BBB", "bbb");
map.put("CCC", "ccc");
//遍历集合,键找值
Set keyResult = map.keySet();
for (String key : keyResult) {
String value = map.get(key);
System.out.println(key + " = " + value);
}
}
}
通过entrySet方法获取所有的键值对对象,返回一个Set集合;
遍历这个Set集合,得到里面每一个键值对对象;
利用getKey() 和 getValue()方法获取键和值
public class MapDemo2 {
public static void main(String[] args) {
//创建集合对象
Map map = new HashMap<>();
//添加元素
map.put("AAA", "aaa");
map.put("BBB", "bbb");
map.put("CCC", "ccc");
//遍历集合,键值对
Set> entries = map.entrySet();
for (Map.Entry entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
方法名称 | 说明 |
---|---|
default void forEach(BiConsumer super K,? super V> action) | 结合lambda遍历Map集合 |
利用lambda表达式进行遍历
底层:其实就是利用第二种方式进行遍历,依次得到每一个键和值,再调用accept方法
public class MapDemo4 {
public static void main(String[] args) {
//创建集合对象
Map map = new HashMap<>();
//添加元素
map.put("AAA", "aaa");
map.put("BBB", "bbb");
map.put("CCC", "ccc");
//遍历集合,内部类
map.forEach(new BiConsumer() {
@Override
public void accept(String s, String s2) {
System.out.println(s+"="+s2);
}
});
System.out.println("-------------------------------------------");
//遍历集合,lambda表达式
map.forEach(( s, s2)->System.out.println(s+"="+s2));
}
}
HashMap是Map里面的一个实现类
直接使用Map里面的方法就可以了
特点都是由键决定的:无序、不重复、无索引
HashMap跟HashSet底层原理是一模一样的,都是哈希表结构
依赖hashcode方法和equals方法保证键的唯一
如果键存储的是自定义对象,需要重写hashcode和equals方法
如果值存储自定义对象,不需要重写hashcode和equals方法
需求 创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历 要求:同姓名,同年龄认为是同一个学生
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);
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
/**
* 需求
* 创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历
* 要求:同姓名,同年龄认为是同一个学生
*/
public class MapDemo5 {
public static void main(String[] args) {
//创建map集合对象
HashMap map = new HashMap<>();
Student s1 = new Student("zhangsan",23);
Student s2 = new Student("lisi",24);
Student s3 = new Student("zhangsan",23);
map.put(s1,"陕西");
map.put(s2,"山西");
map.put(s3,"北京");
map.forEach((Student student, String s)->System.out.println(student + "=" + s));
}
}
需求 某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是A、B、C、D。每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。
public class MapDemo6 {
public static void main(String[] args) {
//利用数组存储4个景点
String[] strs = {"A", "B", "C", "D"};
//利用随机数模拟80名同学投票
ArrayList list = new ArrayList<>();
//将投票结果存入list
Random random = new Random();
for (int i = 0; i < 80; i++) {
int index = random.nextInt(strs.length);
list.add(strs[index]);
}
//统计
HashMap hashMap = new HashMap<>();
//遍历list,将其元素存入map
for (String s : list) {
//如果hashmap里面已经有这个键
//获取其值,然后加1
if (hashMap.containsKey(s)) {
Integer value = hashMap.get(s);
value++;
hashMap.put(s, value);
} else {
hashMap.put(s, 1);
}
}
//找出最大值
Integer max = 0;
Set set = hashMap.keySet();
for (String s : set) {
if (hashMap.get(s) >= max){
max = hashMap.get(s);
}
}
//找出那个景点,
Set> entries = hashMap.entrySet();
for (Map.Entry entry : entries) {
if (entry.getValue() == max){
System.out.println(entry.getKey());
}
}
}
}
由键决定:有序、不重复、无索引。 这里的有序指的是保证存储和取出的元素顺序一致 原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序,。
public class MapDemo7 {
public static void main(String[] args) {
LinkedHashMap stringIntegerLinkedHashMap = new LinkedHashMap<>();
stringIntegerLinkedHashMap.put("a",1);
stringIntegerLinkedHashMap.put("c",3);
stringIntegerLinkedHashMap.put("b",2);
System.out.println(stringIntegerLinkedHashMap); //{a=1, c=3, b=2} 存入和取出的元素顺序一致
}
}
TreeMap跟Treeset底层原理一样,都是红黑树结构的。 由键决定特性:不重复、无索引、可排序 可排序:对键进行排序 注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则 代码书写两种排序规则 实现Comparable接口,指定比较规则, 创建集合时传递Comparator比较器对象,指定比较规则。
键:整数表示id 值:字符串表示商品名称 要求:按照id的升序排列、按照id的降序排列
public class MapDemo8 {
public static void main(String[] args) {
//创建集合对象,同时处传递Comparator比较器对象,指定比较规则
TreeMap treeMap = new TreeMap<>(( o1, o2)->o2 - o1);
//添加元素
treeMap.put(1,"奥利奥");
treeMap.put(9,"九个核桃");
treeMap.put(7,"雷碧");
treeMap.put(2,"汪汪");
treeMap.put(3,"康帅傅");
treeMap.put(5,"哇哈哈哈");
Set> entries = treeMap.entrySet();
for (Map.Entry entry : entries) {
System.out.print(entry.getKey() + entry.getValue() + " "); //9九个核桃 7雷碧 5哇哈哈哈 3康帅傅 2汪汪 1奥利奥
}
}
}
键:学生对象 值:籍贯 要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人。
public class Student implements Comparable {
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;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
@Override
public int compareTo(Student o) {
int i = this.getAge() - o.getAge();
i = i == 0 ? this.getName().compareTo(o.getName()) : i;
return i;
}
}
public class MapDemo9 {
public static void main(String[] args) {
Student s1 = new Student("zhangsan",23);
Student s2 = new Student("lisi",24);
Student s3 = new Student("wangwu",25);
Student s4 = new Student("a",23);
Student s5 = new Student("a",23);
TreeMap studentStringTreeMap = new TreeMap<>();
studentStringTreeMap.put(s1,"河北");
studentStringTreeMap.put(s2,"河南");
studentStringTreeMap.put(s3,"北京");
studentStringTreeMap.put(s4,"上海");
studentStringTreeMap.put(s5,"湖南");
studentStringTreeMap.forEach((Student student, String s)-> System.out.println(student + s) );
}
}
统计个数 需求:字符串“aababcabcdabcde” 请统计字符串中每一个字符出现的次数,并按照以下格式输出 输出结果: a(5)b(4)c(3)d(2)e(1)
public class MapDemo10 {
public static void main(String[] args) {
String str = "aababcabcdabcde";
TreeMap tm = new TreeMap<>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (tm.containsKey(c)) {
Integer integer = tm.get(c);
tm.put(c,++integer);
}else {
tm.put(c,1);
}
}
StringBuilder stringBuilder = new StringBuilder();
tm.forEach((Character key, Integer value) -> stringBuilder.append(key).append("(").append(value).append(")"));
System.out.println(stringBuilder); //a(5)b(4)c(3)d(2)e(1)
}
}
在JDK5的时候,出现了可变参数,所谓可变参数,就是方法形参的个数是可以发生变化的 格式 : 属性类型...名字
在底层,可变参数底层就是一个数组
比如,我现在要计算n个整数的和,以前我们先创建一个数组,将整数存入数组中,然后将数组传递给求和的方法,
现在,我们不用自己创建数组了,Java会帮我们创建好
以前,需要我们自己创建数组
public class ArgsDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
System.out.println(getSum(arr));
}
public static int getSum(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
}
现在,利用可变参数,Java会帮我们创建数组
public class ArgsDemo {
public static void main(String[] args) {
System.out.println(getSum(1,2,3,4,5,6,7,8,9,10));
}
public static int getSum(int...arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
}
细节:
1.在方法的形参中最多只能写一个可变参数 2.在方法的形参当中,如果出了可变参数以外,还有其他的形参,那么可变参数要写在最后
● java.util.Collections:是集合工具类 ● 作用:Collections不是集合,而是集合的工具类
方法名称 | 说明 |
---|---|
public static |
批量添加元素 |
public static void shuffle(List> list) | 打乱List集合元素的顺序 |
public static |
排序 |
public static |
根据指定的规则进行排序 |
public static |
以二分查找法查找元素 |
public static |
拷贝集合中的元素 |
public static |
使用指定的元素填充集合 |
public static |
根据默认的自然排序获取最大/小值 |
public static |
交换集合中指定位置的元素 |
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList<>();
//批量添加元素
System.out.println("----------批量添加元素----------");
Collections.addAll(arrayList, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(arrayList);
System.out.println("------------------------------");
//打乱List集合元素的顺序
System.out.println("----------打乱List集合元素的顺序----------");
Collections.shuffle(arrayList);
System.out.println(arrayList);
System.out.println("------------------------------");
//根据指定的规则进行排序 这里指定倒序
System.out.println("----------根据指定的规则进行排序----------");
Collections.sort(arrayList, (o1, o2) -> o2 - o1);
System.out.println(arrayList);
System.out.println("------------------------------");
//排序 默认整数是从小到大
System.out.println("----------排序----------");
Collections.sort(arrayList);
System.out.println(arrayList);
System.out.println("------------------------------");
//以二分查找法查找元素
System.out.println("----------以二分查找法查找元素----------");
int i = Collections.binarySearch(arrayList, 1);
System.out.println(i);
System.out.println("------------------------------");
//拷贝集合中的元素
System.out.println("----------拷贝集合中的元素----------");
ArrayList arrayList1 = new ArrayList<>();
Collections.addAll(arrayList1,0,0,0,0,0,0,0,0,0,0);
Collections.copy(arrayList1,arrayList);
System.out.println(arrayList1);
System.out.println("------------------------------");
}
}
班级里有N个学生,实现随机点名器。
public class Test1 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//添加元素
Collections.addAll(arrayList,"赵一","钱二","孙三","李四","周五","吴六","郑七","王八","冯九","陈十");
//随机1
Random random = new Random();
System.out.println(arrayList.get(random.nextInt(arrayList.size())));
//随机2
Collections.shuffle(arrayList);
System.out.println(arrayList.get(0));
}
}
班级里有N个学生,实现随机点名器。 要求: 70%的概率随机到男生 30%的概率随机到女生
public class Test1 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//添加元素
Collections.addAll(arrayList,1,1,1,1,1,1,1,0,0,0);
//随机2
Collections.shuffle(arrayList);
Integer index = arrayList.get(0);
ArrayList boy = new ArrayList<>();
ArrayList girl = new ArrayList<>();
Collections.addAll(boy,"赵一","钱二","孙三","李四","周五","吴六","郑七","王八","冯九","陈十");
Collections.addAll(girl,"赵女","钱女","孙女","李女","周女");
if (index == 1){
Collections.shuffle(boy);
System.out.println(boy.get(0));
}else {
Collections.shuffle(girl);
System.out.println(girl.get(0));
}
}
}