Map集合
Map集合
Map集合的概念和特点
概念:
JAVA对于键映射到值的数据对象为了方便操作提供了Map集合
Map之所以被称为双列集合 是由于它有键 有值
Map分类:
- HashMap
- HashTable
- LinkedHashMap
- TreeMap
Map的特点:
所有双列集合的数据结构 只跟键有关 跟值没关系
Map:双列集合 一个键只能映射一个值 键相同 值就会被覆盖
在生活中 有一种数据比较常见 比如一个 学号—学生
1. “s001”----------“张三”
2. “s002”----------“张四”
3. “s003”----------“张五”
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
ArrayList<String> d = new ArrayList<>();
d.add("s001----------张三");
d.add("s002----------张四");
d.add("s003----------张五");
System.out.println(Arrays.toString(d.get(0).split("-+"))); System.out.println(Arrays.toString(d.get(0).split("-+"))); System.out.println(Arrays.toString(d.get(0).split("-+")));
}
}
运行结果:
[s001, 张三]
[s001, 张三]
[s001, 张三]
Process finished with exit code 0
HashMap
//添加元素 d.put(“key”, “value”);
//当键相同 值覆盖 返回的是上一次这个键所映射的旧值
//当键名为英文时键值顺序为有序
//当键名为中文时键值顺序为无序
public class HashM {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
//添加元素
String s1=d.put("a001", "aaa1");
//当键相同 值覆盖 返回的是上一次这个键所映射的旧值
String s2=d.put("a001", "aaa2");
d.put("b002", "aaa3");
d.put("c003", "aaa4");
d.put("安004", "aaa5");
d.put("静004", "aaa5");
System.out.println(d);//顺序为无序
System.out.println(s1);//会被覆盖
System.out.println(s2);
}
}
运行结果:
{静004=aaa5, 安004=aaa5, a001=aaa2, b002=aaa3, c003=aaa4}
null
aaa1
Process finished with exit code 0
HashMap集合清空方法
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put("001", "aa");
d.put("002", "bb");
d.put("003", "cc");
d.put("004", "dd");
//打印集合
System.out.println(d);
//清空集合
d.clear();
//集合长度
System.out.println(d.size());
}
}
运行结果:
{001=aa, 002=bb, 003=cc, 004=dd}
0
Process finished with exit code 0
HashMap集合的其他方法
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put("111", "aa");
d.put("222", "ss");
d.put("333", "dd");
d.put("444", "ff");
//集合长度
System.out.println("集合元素个数"+d.size());
//返回的是键对应的值
String dd = d.remove("333");
System.out.println("返回删除的333键映射的值"+dd);
System.out.println(d);
//键是否存在
System.out.println("查看333键是否存在"+d.containsKey("333"));
System.out.println("查看222键是否存在"+d.containsKey("222"));
//通过键来获取值
System.out.println("通过键位111查询映射的值"+d.get("111"));
//通过键来获取值 找不到返回备用
System.out.println("通过键来获取值 找不到返回备用"+d.getOrDefault("dd", "DD"));
//判断集合是否为空
System.out.println("判断集合是否为空"+d.isEmpty());
}
}
运行结果:
集合元素个数4
返回删除的333键映射的值dd
{111=aa, 222=ss, 444=ff}
查看333键是否存在false
查看222键是否存在true
通过键位111查询映射的值aa
通过键来获取值 找不到返回备用DD
判断集合是否为空false
Process finished with exit code 0
双列集合的遍历
键找值 遍历HashMap
import java.util.HashMap;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put("111", "aa");
d.put("222", "bb");
d.put("333", "cc");
d.put("444", "dd");
Set<String> dd = d.keySet();
for (String s : dd) {
System.out.println(s+"\t"+d.get(s));
}
}
}
运行结果:
111 aa
222 bb
333 cc
444 dd
Process finished with exit code 0
entrySet() 遍历HashMap
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put("111", "aa");
d.put("222", "bb");
d.put("333", "cc");
d.put("444", "dd");
Set<Map.Entry<String, String>> ff = d.entrySet();
for (Map.Entry<String, String> ee : ff) {
System.out.println(ee);
}
}
}
运行结果:
111=aa
222=bb
333=cc
444=dd
Process finished with exit code 0
值的获取values()
import java.util.Collection;
import java.util.HashMap;
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put("111", "aa");
d.put("222", "bb");
d.put("333", "cc");
d.put("444", "dd");
Collection<String> dd = d.values();
for (String s : dd) {
System.out.println(s);
}
}
}
运行结果:
aa
bb
cc
dd
Process finished with exit code 0
键名相同与不同问题
键名为string 值为自定义类(student)
当键名为String类型时,如果键名相同,则会覆盖重复键名映射的元素
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
HashMap<String, Student> d = new HashMap<>();
d.put("111", new Student("aa"));
d.put("222", new Student("bb"));
d.put("333", new Student("cc"));
d.put("444", new Student("dd"));
d.put("333", new Student("ee"));
d.put("444", new Student("ff"));
Set<Map.Entry<String, Student>> ff = d.entrySet();
for (Map.Entry<String, Student> ee : ff) {
System.out.println(ee);
}
}
}
class Student {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
运行结果:
111=Student{name='aa'}
222=Student{name='bb'}
333=Student{name='ee'}
444=Student{name='ff'}
Process finished with exit code 0
键名为自定义类时(Stud) 值为string
此时,键是否相同比较的是地址值,而不是字面值
因为比较的是地址值,虽然字面值相同,但是不会出现键名相同覆盖映射的元素
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
HashMap<Stud, String> d = new HashMap<>();
d.put(new Stud("aa"), "111");
d.put(new Stud("bb"), "222");
d.put(new Stud("aa"), "333");
d.put(new Stud("cc"), "444");
d.put(new Stud("dd"), "555");
d.put(new Stud("cc"), "666");
Set<Map.Entry<Stud, String>> ff = d.entrySet();
for (Map.Entry<Stud, String> ee : ff) {
System.out.println(ee);
}
}
}
class Stud {
private String name;
public Stud(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
运行结果:
Student{name='bb'}=222
Student{name='dd'}=555
Student{name='cc'}=444
Student{name='cc'}=666
Student{name='aa'}=111
Student{name='aa'}=333
Process finished with exit code 0
原因:
当键位为String类时,String类默认重写了HashCode()与equals()方法,比较的是键位的字面值,所以会产生相同键位映射的值被覆盖的情况。
当键位为自定义类时。因为自定义类没有重写HashCode()与equals()方法,比较的是键位的地址值,所以不会产生相同键位映射的值被覆盖的情况
案例:
重写自定义类的HashCode()与equals()方法后。以自定义类的对象为键值,此时键值比较的是字面值,当键位相同时,会覆盖映射的元素。
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public class Test1 {
public static void main(String[] args) {
HashMap<Stud,String> d = new HashMap<>();
d.put(new Stud("aa"), "111");
d.put(new Stud("bb"), "222");
d.put(new Stud("aa"), "333");
d.put(new Stud("cc"), "444");
d.put(new Stud("dd"), "555");
d.put(new Stud("cc"), "666");
Set<Map.Entry<Stud,String>> ff = d.entrySet();
for (Map.Entry<Stud,String> ee : ff) {
System.out.println(ee);
}
}
}
class Stud{
private String name;
public Stud(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Stud stud = (Stud) o;
return Objects.equals(name, stud.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
运行结果:
Student{name='aa'}=333
Student{name='bb'}=222
Student{name='cc'}=666
Student{name='dd'}=555
Process finished with exit code 0
Hashtable
Hashtable与HashMap的区别:
- HashMap键的数据结构是哈希表 键无序且唯一 并且允许使用null值和null键 线程不安全 效率高
- Hashtable不允许null值和null键 线程安全 效率低
import java.util.HashMap;
import java.util.Hashtable;
public class Test1 {
public static void main(String[] args) {
HashMap<String, String> d = new HashMap<>();
d.put(null,null);
Hashtable<String, String> dd = new Hashtable<>();
dd.put(null,"hh");
dd.put("nu",null);
dd.put(null,null);
}
}
运行结果:报错
Exception in thread "main" java.lang.NullPointerException
LinkedHashMap
特点:键的数据结构是链表和哈希表 键有序且唯一 链表保证有序 哈希表保证唯一
import java.util.LinkedHashMap;
public class Test1 {
public static void main(String[] args) {
LinkedHashMap<String, String> d = new LinkedHashMap<>();
d.put("111", "aa");
d.put("222", "bb");
d.put("222", "BB");
d.put("333", "cc");
d.put("333", "CC");
d.put("444", "dd");
d.put("555", "ee");
d.put("666", "ff");
System.out.println(d);
}
}
运行结果:
{111=aa, 222=BB, 333=CC, 444=dd, 555=ee, 666=ff}
Process finished with exit code 0
TreeMap
特点:
当键名为数值时会进行大小排序
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Test1 {
public static void main(String[] args) {
TreeMap<Integer, String> d = new TreeMap<>();
d.put(111, "aa");
d.put(222, "bb");
d.put(777, "BB");
d.put(333, "cc");
d.put(888, "CC");
d.put(444, "dd");
d.put(555, "ee");
d.put(666, "ff");
System.out.println(d);
}
}
运行结果:
{111=aa, 222=bb, 333=cc, 444=dd, 555=ee, 666=ff, 777=BB, 888=CC}
Process finished with exit code 0
当键名为字符串时会按照字典索引排序
import java.util.LinkedHashMap;
import java.util.TreeMap;
public class Test1 {
public static void main(String[] args) {
TreeMap<String, String> d = new TreeMap<>();
d.put("aa","1");
d.put("ee","5" );
d.put("bb","2 ");
d.put("cc","3");
d.put("ff","6" );
d.put("dd","4");
d.put("gg","7" );
d.put("qq","21");
System.out.println(d);
}
}
运行结果:
{aa=1, bb=2 , cc=3, dd=4, ee=5, ff=6, gg=7, qq=21}
Process finished with exit code 0
当键名为自定义类型时 要传入比较器进行比较
案例:
以自定义类(Stude)的成员变量(age)进行排序
package com.westos.X2;
import java.util.*;
public class Test1 {
public static void main(String[] args) {
TreeMap<Stude, String> d = new TreeMap<>(new Comparator<Stude>() {
@Override
public int compare(Stude o1, Stude o2) {
int num = o1.getAge() - o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
return num2;
}
});
d.put(new Stude("cc", 12), "33");
d.put(new Stude("bb", 13), "22");
d.put(new Stude("dd", 14), "44");
d.put(new Stude("aa", 12), "11");
d.put(new Stude("ee", 11), "55");
d.put(new Stude("ff", 22), "66");
Set<Map.Entry<Stude, String>> ff = d.entrySet();
for (Map.Entry<Stude, String> ee : ff) {
System.out.println(ee);
}
}
}
class Stude {
private String name;
private int age;
public Stude(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Stude{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行结果:
Stude{name='ee', age=11}=55
Stude{name='aa', age=12}=11
Stude{name='cc', age=12}=33
Stude{name='bb', age=13}=22
Stude{name='dd', age=14}=44
Stude{name='ff', age=22}=66
Process finished with exit code 0
练习:
利用Map统计字符个数
import java.util.Scanner;
import java.util.TreeMap;
public class Test1 {
public static void main(String[] args) {
TreeMap< Character,Integer> dd = new TreeMap<>();
Scanner d = new Scanner(System.in);
System.out.println("请输入字符串");
String s=d.nextLine();
for (int i = 0; i < s.length(); i++) {
if(!dd.containsKey(s.charAt(i))){
dd.put(s.charAt(i),1);
}else{
int m=dd.get(s.charAt(i));
m++;
dd.put(s.charAt(i),m);
}
}
System.out.println(dd);
}
}
运行结果:
请输入字符串
zhaotianxiao
{a=3, h=1, i=2, n=1, o=2, t=1, x=1, z=1}
Process finished with exit code 0
本文地址:https://blog.csdn.net/qq_39153706/article/details/107888179
上一篇: Archlinux 安装教程图文详解
下一篇: 酷毙了!Nike有双能自己系鞋带的球鞋