Java_18_Map集合

Map集合

  1. Map集合是另一个集合体系。
    Collection是单值集合体系。

  2. Map集合是一种双列集合,每个元素包含两个值。
    Map集合的每个元素的格式:key=value(键值对元素)。
    Map集合也被称为“键值对集合”。

  3. Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , …}

  4. Map集合有啥用?

    1. Map集合存储的信息更加的具体丰富。
      Collection: [“苍老师”,“日本”,“女”,“动作演员”,23,“广州”]
      Map : {name=“苍老师” , jiaxiang=小日本 , sex=“女” , age = 23 , addr=广州}

    2. Map集合很适合做购物车这样的系统。
      Map: {娃娃=30 , huawei=1 , iphonex=1}

  5. 注意:集合和泛型都只能支持引用数据类型,集合完全可以称为是对象容器,存储都是对象。

  6. Map集合的体系:
    Map<K , V>(接口,Map集合的祖宗类)
    TreeMap<K , V>
    HashMap<K , V>(实现类,经典的,用的最多)
    LinkedHashMap<K, V>(实现类)

  7. Map集合的特点:
    1.Map集合的特点都是由键决定的。
    2.Map集合的键是无序,不重复的,无索引的。
    Map集合后面重复的键对应的元素会覆盖前面的整个元素!
    3.Map集合的值无要求。
    4.Map集合的键值对都可以为null。

HashMap:元素按照键是无序,不重复,无索引,值不做要求。
LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。

范例

public class MapDemo {
    public static void main(String[] args) {
        // 一行经典代码
        Map<String , Integer> maps = new HashMap<>();
        maps.put("娃娃",1);
        maps.put("huawei",10);
        maps.put("iphoneXS",2);
        maps.put(null , null );
        maps.put("娃娃",30);
        maps.put("特仑苏",2);
        System.out.println(maps);
    }
}

Map的几个重要API

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
    • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
    • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
    • public Set keySet(): 获取Map集合中所有的键,存储到Set集合中。
    • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。
    • public boolean containKey(Object key):判断该集合中是否有此键。
public class MapDemo {
    public static void main(String[] args) {
        Map<String , Integer> maps = new HashMap<>();
        // 1.添加元素: 无序,不重复,无索引。
        maps.put("iphoneX",10);
        maps.put("娃娃",30);
        maps.put("iphoneX",100);//  Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
        maps.put("huawei",1000);
        maps.put("生活用品",10);
        maps.put("手表",10);
        // {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
        System.out.println(maps);

        // 2.清空集合
        //maps.clear();
        //System.out.println(maps);

        // 3.判断集合是否为空,为空返回true ,反之!
        System.out.println(maps.isEmpty());

        // 4.根据键获取对应值。
        //Integer value = maps.get("娃娃");
        //System.out.println(value);
        System.out.println(maps.get("娃娃"));

        // 5.根据键删除整个元素。(删除键会返回键的值)
        maps.remove("iphoneX");
        System.out.println(maps);

        // 6.判断是否包含某个键 ,包含返回true ,反之
        System.out.println(maps.containsKey("手表")); // true
        System.out.println(maps.containsKey(10)); // false

        // 7.判断是否包含某个值。
        System.out.println(maps.containsValue(1000)); // true
        System.out.println(maps.containsValue(10)); // true
        System.out.println(maps.containsValue("30")); // false 包含的是整数30不是字符串。

        // 8.获取全部键的集合:public Set<K> keySet()
        // Map集合的键是无序不重复的,所以返回的是一个Set集合。
        Set<String> keys = maps.keySet();
        for (String key : keys) {
            System.out.println(key);
        }

        // 9.获取全部值的集合:Collection<V> values();
        // Map集合的值是不做要求的,可能重复,所以值要用Collection集合接收!
        Collection<Integer> values = maps.values();
        for (Integer value : values) {
            System.out.println(value);
        }

        // 10.集合的大小
        System.out.println(maps.size());

        // 11.合并其他Map集合。(拓展)
        Map<String,Integer> maps2 = new HashMap<>();
        maps2.put("xiaoMi" , 1);
        maps2.put("🔨手机" , 10);
        maps2.put("手表" , 10000);
        maps.putAll(maps2); // 把Map集合maps2的数据全部倒入到maps集合中去
        System.out.println(maps);

    }
}

遍历

  1. Map集合的遍历方式有:3种。
    (1)“键找值”的方式遍历:先获取Map集合全部的键,再根据遍历键找值。
    (2)“键值对”的方式遍历:难度较大。
    (3)JDK 1.8开始之后的新技术:Lambda表达式。(暂时了解)

  2. “键找值”的方式遍历Map集合。
    1.先获取Map集合的全部键的Set集合。
    2.遍历键的Set集合,然后通过键找值。
    小结:
    代码简单,需要记住!

 // 获取当前Map集合的全部键的集合 。
        Set<String> keys = maps.keySet();
        System.out.println(keys);
        // [huawei, 手表, 生活用品, iphoneX, 娃娃]
        //          key
        // b.通过遍历键然后通过键取对应的值
        for (String key : keys) {
            // 过键取对应的值
            Integer value = maps.get(key);
            System.out.println(key + "=" + value);
        }
  1. “键值对”的方式遍历:
    1. 把Map集合转换成一个Set集合:Set<Map.Entry<K, V>> entrySet();
    2. 此时键值对元素的类型就确定了,类型是键值对实体类型:Map.Entry<K, V>
    3. 接下来就可以用foreach遍历这个Set集合,类型用Map.Entry<K, V>

  2. “键值对”的方式遍历:更加面向对象的方式,代码复杂。

  3. “键值对”想把键值对当成一个整体遍历,也就是直接使用foreach遍历:
    for(被遍历集合的元素类型 变量:集合名称){}
    但是发现Map集合的键值对数据直接是没有元素类型的,foreach无法直接遍历Map集合。
    👇
    把Map集合通过代码Set<Map.Entry<K, V>> entrySet()转换成Set集合。
    👇
    Set<Map.Entry<String,Integer>> entries = maps.entrySet();
    👇
    entries = [(huawei=1000), (手表=10), (生活用品=10), (iphoneX=100), (娃娃=30) ]
    // entry
    此时键值对元素才能作为一个整体就有了类型。类型是 Map.Entry<String,Integer>实体类型

public class MapDemo02 {
    public static void main(String[] args) {
        Map<String , Integer> maps = new HashMap<>();
        // 1.添加元素: 无序,不重复,无索引。
        maps.put("娃娃",30);
        maps.put("iphoneX",100);//  Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
        maps.put("huawei",1000);
        maps.put("生活用品",10);
        maps.put("手表",10);
        System.out.println(maps);
        // maps = {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
        //
        Set<Map.Entry<String,Integer>> entries = maps.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
             String key = entry.getKey();
             Integer value = entry.getValue();
             System.out.println(key + "=>" + value);
        }
    }
}

存储自定义类型

Map集合的键和值都可以存储自定义类型。

  1. 小结:
    Map集合的键和值都可以存储自定义类型。
    如果希望Map集合认为自定义类型的键对象重复了,必须重写对象的hashCode()和equals()方法

Orange类作存储类型

public class Orange {
    private String name;
    private double weight;
    private String price;
    public Orange() {
    }

    public Orange(String name, double weight, String price) {
        this.name = name;
        this.weight = weight;
        this.price = price;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Orange orange = (Orange) o;
        return Double.compare(orange.weight, weight) == 0 &&
                Objects.equals(name, orange.name) &&
                Objects.equals(price, orange.price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, weight, price);
   }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }

    public String toString() {
        return "Orange{name = " + name + ", weight = " + weight + ", price = " + price + "}";
    }
}

Main

public class MapDemo02 {
    public static void main(String[] args){
        Map<Oranges,String> maps = new HashMap<>();
        Oranges o1 = new Oranges("黄橘子",20.3 , "贼便宜!");
        Oranges o2 = new Oranges("黑橘子",30.3 , "坏了");
        Oranges o3 = new Oranges("青橘子",34.3 , "9.9包邮");
        Oranges o4 = new Oranges("黄橘子",20.3 , "贼便宜!");

        maps.put(o1,"江西");
        maps.put(o2,"江苏");
        maps.put(o3,"山东");
        maps.put(o4,"浙江");

        System.out.println(maps);
    }
}

LinkedHashMap

  1. LinkedHashMap是HashMap的子类。
    1. 添加的元素按照键有序,不重复的。
    HashSet集合相当于是HashMap集合的键都不带值。
    LinkedHashSet集合相当于是LinkedHashMap集合的键都不带值。

  2. 底层原理完全一样,都是基于哈希表按照键存储数据的,
    只是HashMap或者LinkedHashMap的键都多一个附属值。

  3. 小结:
    HashMap集合是无序不重复的键值对集合。
    LinkedHashMap集合是有序不重复的键值对集合。
    他们都是基于哈希表存储数据,增删改查都很好。

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        Map<String , Integer> maps = new LinkedHashMap<>();
        maps.put("iphoneX",10);
        maps.put("娃娃",30);
        maps.put("iphoneX",100); // 依然是保留前面的位置,只是替换其值!
        maps.put("huawei",1000);
        maps.put("生活用品",10);
        maps.put("手表",10);
        System.out.println(maps);
    }
}

TreeMap

  1. TreeMap集合按照键是可排序不重复的键值对集合。(默认升序)
  2. TreeMap集合按照键排序的特点与TreeSet是完全一样的。
  3. 小结:
    TreeMap集合和TreeSet集合都是排序不重复集合
    TreeSet集合的底层是基于TreeMap,只是键没有附属值而已。
    所以TreeMap集合指定大小规则有2种方式:
    a.直接为对象的类实现比较器规则接口Comparable,重写比较方法(拓展方式)
    b.直接为集合设置比较器Comparator对象,重写比较方法
  // 比较者: this
    // 被比较者: o
    // 需求:按照价格排序!
    @Override
    public int compareTo(Object o) {
        // 浮点型的大小比较建议使用Java自己的API:
        // public static int compare(double d1, double d2)
        return  Double.compare(this.price , ((Pig)o).price);
    }

浮点型有专门的比较API 默认升序,降序加个负号就行。

public class TreeMapDemo {
    public static void main(String[] args) {
        Map<Integer,String> maps = new TreeMap<>();
        maps.put(1000000,"张三");
        maps.put(1000000,"张三1");
        maps.put(10000,"李四");
        maps.put(10,"王五");
        maps.put(24244,"张麻子");
        System.out.println(maps);

        Map<Pig,String> pigs = new TreeMap<>();
        pigs.put(new Pig("🐖佩奇",99.5 , 500.0), "荷兰");
        pigs.put(new Pig("🐖乔治",99.4 , 605.0), "澳大利亚");
        pigs.put(new Pig("🐗野猪",199.4 , 305.0), "山上");
        pigs.put(new Pig("🐗野猪",199.4 , 305.0), "山上2");
        System.out.println(pigs);


        //  public TreeMap(Comparator<? super K> comparator)
        Map<Pig,String> pigs1 = new TreeMap<>(new Comparator<Pig>() {
            @Override
            public int compare(Pig p1, Pig p2) {
                return Double.compare(p1.getWeight() , p2.getWeight());
            }
        });
        pigs1.put(new Pig("🐖佩奇",99.5 , 500.0), "荷兰");
        pigs1.put(new Pig("🐖乔治",99.4 , 605.0), "澳大利亚");
        pigs1.put(new Pig("🐗野猪",199.4 , 305.0), "山上");
        pigs1.put(new Pig("🐗野猪",199.4 , 305.0), "山上2");
        System.out.println(pigs1);
    }
}

案例

  1. 目标:输出一个字符串中每个字符出现的次数。(经典面试题)

  2. 分析:
    (1)键盘录入一个字符串。aabbccddaa123。
    (2)定义一个Map集合,键是每个字符,值是其出现的次数。 {a=4 , b=2 ,…}
    (3)遍历字符串中的每一个字符。
    (4)拿着这个字符去Map集合中看是否有这个字符键,有说明之前统计过,其值+1
    没有这个字符键,说明该字符是第一次统计,直接存入“该字符=1”

public class MapDemo03 {
    public static void main(String[] args){
        // (1)键盘录入一个字符串。aabbccddaa123。
        Scanner scanner = new Scanner(System.in);
        System.out.print("请您输入一个字符串:");
        String tmp = scanner.nextLine();
        // (2)定义一个Map集合,键是每个字符,值是其出现的次数。
        Map<Character,Integer> iCount = new HashMap<>();
        // (3)遍历字符串中的每一个字符。
        for(int i = 0;i < tmp.length();i ++){
            char nowLocal = tmp.charAt(i);  //定义变量存当前位置的字符
            // (4)拿着这个字符去Map集合中看是否有这个字符键,有说明之前统计过,其值+1
            //   没有这个字符键,说明该字符是第一次统计,直接存入“该字符=1”
            if(iCount.containsKey(nowLocal)) iCount.put(nowLocal,iCount.get(nowLocal) + 1);
            else iCount.put(nowLocal,1);
        }
        System.out.println(iCount);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐鑫本鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值