欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Map集合

程序员文章站 2023-01-29 23:19:13
Map是双列集合的根接口,用于存储具有映射关系的数据。 根据key来区分每一项、获取对应的value,所以key不能重复。 key、value都可以是任意类型的数据。 Map提供了一个内部类Entry用来封装键值对,一个键值对就是一个Entry实例。 Map的常用方法(所有子类都可以直接使用): v ......

Map集合

Map集合的概念和特点

概念:

JAVA对于键映射到值的数据对象为了方便操作提供了Map集合

Map之所以被称为双列集合 是由于它有键 有值

Map分类:

  1. HashMap
  2. HashTable
  3. LinkedHashMap
  4. 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的区别:

  1. HashMap键的数据结构是哈希表 键无序且唯一 并且允许使用null值和null键 线程不安全 效率高
  2. 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

相关标签: Map