Java双列集合

本文详细介绍了Java中的Map接口,包括Map与Collection的区别,常用方法如put、remove和get,以及两种遍历思路。重点讲解了HashMap、LinkedHashMap的底层实现和它们与Hashtable的关系,同时提及了Collections工具类在排序中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Map

1.1概述

  • Map:双列集合的顶层接口

  • Map:描述的就是一个数据(key)到另一个数据(value)的对应关系

    • 一个数据(key):就是有规律的,容易记忆的,简单的一个数据

    • 一个数据(value):没有规律的,不容易记忆的,复杂的一个数据

    • 大多数都是根据key来寻找value

  • Map的特点:

    • Key(键)是唯一的

    • Value(值)不是唯一的

  • Map和Collection的区别:

    • Map是双列集合

    • Collection是单列集合

    • Map的键是唯一的,Collection中的Set子接口中的元素是唯一的

    • Map的所有操作是针对《键》有效,Collection中的set子接口中的操作针对《元素》有效

1.2Map中的常用方法

  • 增加键值对:

    • put(K key, V value)

  • 删除方法:

    • 根据给定的键,删除对应的键值对:

      • remove (K key)

      • 清空集合:clear()

  • 获取方法:

    • 获取集合的大小:size()

    • 获取键对应的值,根据给定的键,获取对应的值:V get(K key)

  • 判断方法:

    • 判断集合中是否存在某个键:containsKey(Object obj)

    • 判断集合中是否存在某个值:containsValue(Object obj)

  • 修改方法:

    • 根据给定的键,修改对应的值:put(K key, V value)

      • 如果在集合中已经存在key这个键,那么使用put方法,就是修改其对应的值

      • 如果集合中不存在key这个键,那么使用put方法,就是在集合中增加了一个键值对

代码示例:
import java.util.HashMap;
import java.util.Map;
/**
 *Map中的常用方法
 */
public class Simple01 {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        map.put("c", 4);
        System.out.println(map);
        map.remove("a");
        System.out.println(map);
        map.clear();
        System.out.println(map);
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        map.put("d", 4);
        System.out.println(map.size());
        Integer value = map.get("c");
        System.out.println(value);
        boolean b = map.containsKey("bb");
        System.out.println(b);
        boolean b1 = map.containsValue(4);
        System.out.println(b1);
        map.put("a", 11);
        System.out.println(map.get("a"));
        map.put("aa", 111);
        System.out.println(map);
    }
}

1.3 Map集合的第一种遍历思路【熟练掌握】

  • 获取Map集合中的所有键,放到一个Set集合中,遍历该Set集合,获取到每一个键,根据键再来获取对应的值。【根据键获取值】

  • 获取Map集合中的所有键并存入Set

  • Set<K>  keySet()    //k是你map中键的类型,Set<String> set = map.keySet();

  • 遍历Set集合的两种方法:

    • 迭代器

    • 增强for循环

  • 拿到每个键之后,获取对应的值 V get(K key)

  • 特点: 获取了所有的键的集合之后,仍然要依赖原来的Map集合

代码示例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Map集合的第一种遍历思路【熟练掌握】
 */

public class Simple02 {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap();
        map.put("aaa", 111);
        map.put("bbb", 222);
        map.put("ccc", 333);
        map.put("ddd", 444);
        System.out.println(map);
        // test1(map);//第一种遍历思路的第一种遍历方式迭代器(map)
        test2(map);// 第一种遍历思路的第二种遍历方式增强for(map)
    }

    // 第一种遍历思路的第一种遍历方式迭代器(map)
    public static void test1(Map<String, Integer> map) {
        Set<String> set = map.keySet();
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = it.next();
            System.out.println("key是:" + key + "---value是:" + map.get(key));
        }
    }
		// 第一种遍历思路的第二种遍历方式增强for(map)
    public static void test2(Map<String, Integer> map) {
        Set<String> set = map.keySet();
        for (String key : set) {
            System.out.println("key是:" + key + "---value是:" + map.get(key));
        }
    }
}

1.4 Map集合的第二种遍历思路【熟练掌握】

  • 获取Map集合中的所有键值对对象(Entry)到Set集合中,遍历Set集合,拿到的是每个键值对对象(Entry),从这个对象中分别获取键和值【根据键值对对象获取键和值】

  • 根据Map集合获取所有的键值对对象,到一个Set集合中

  • Set<Map.Entry<K, V>>   entrySet()   Set<Map.Entry<String, String>> set = map.entrySet();

  • 遍历Set集合,两种遍历方式

    • 迭代器

    • 增强for循环

  • 获取到某个键值对对象

  • Entry是Map接口中的内部接口,访问的方式:Map.Entry

    • Entry:入口、条目、登记记录

    • Entry的常用方法:

      • getKey()获取当前键值对对象的键

      • getValue()获取当前键值对对象的值

代码示例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Map集合的第二种遍历思路【熟练掌握】
 */
public class Simple03 {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("username", "zhangsan");
        map.put("password", "123456");
        map.put("nickname", "miaomi");
        System.out.println(map);
        test1(map)
        test2(map);

    }

    //迭代器遍历Set集合
    public static void test1(Map<String, String> map) {
        Set<Map.Entry<String, String>> set = map.entrySet();
        System.out.println(set);
        Iterator<Map.Entry<String, String>> iterator = set.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            String key = next.getKey();
            String value = next.getValue();
            System.out.println("键是:" + key + "---值是:" + value);

        }
    }

    // 增强for循环遍历Set(map)
    public static void test2(Map<String, String> map) {
        Set<Map.Entry<String, String>> set = map.entrySet();
        for (Map.Entry<String, String> st : set) {
            System.out.println("键是:" + st.getKey() + "----值是:" + st.getValue());
        }
    }
}

1.5 HashMap

HashMap 的底层实现方式为哈希表,是 HashSet 的实现原理。

image-20230209234735887

  • 就是Map集合使用哈希表的存储方式的一种实现类

  • HashMap存储的是jdk中提供的类型的键,就可以直接保证键的唯一性

  • HashMap中存储的键,是自定义类型(比如下方代码Person),无法保证键的唯一性,原因:虽然都是zhangsan对象,但是这些对象并不是相同的对象,这些对象的哈希值计算结果各不相同,就说明一定不是相同的对象,所以无法保证键的唯一,重写hashCode和equals方法说明:HashMap的键的唯一性和HashSet的元素的唯一性,保证方式都一样

  • HashMap和HashSet的关系:

    • HashSet是由HashMap实现出来的,HashSet就是HashMap的键的那一列

    • 将HashMap中的值的那一列隐藏掉,就变成了HashSet

  • 示例代码:

  • import java.util.HashMap;
    import java.util.Objects;
    
    /**
     * HashMap;
     */
    public class Simple04 {
    
        public static void main(String[] args) {
            HashMap<Person, String> hm = new HashMap<>();
            hm.put(new Person("张三", 23), "北京");
            hm.put(new Person("张三", 23), "上海");
            hm.put(new Person("张三", 23), "广州");
            System.out.println(hm);
            test1_HashMap存储jdk的键();
        }
    
        private static void test1_HashMap存储jdk的键() {
            HashMap<String, Integer> hm = new HashMap<>();
            hm.put("abc", 1);
            hm.put("abc", 3);
            hm.put("ab", 2);
            hm.put("ab", 4);
            System.out.println();
            System.out.println("*******************");
            System.out.println();
            System.out.println(hm);
        }
    }
    
    class Person {
        String name;
        int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

1.6 LinkedHashMap

  • 是HashMap的一个子类

  • 实现原理哈希表+链表

  • 和HashMap不同之处:具有可预知的迭代顺序,存储键值对的顺序和遍历集合时取出键值对的顺序一致。

  • 代码示例:

  • import java.util.LinkedHashMap;
    
    /**
     * LinkedHashMap
     */
    public class Simple05 {
    
        public static void main(String[] args) {
            LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
            lhm.put("aa", 3);
            lhm.put("bb", 3);
            lhm.put("cc", 2);
            lhm.put("dd", 4);
            System.out.println(lhm);
        }
    }

1.7 HashMap和Hashtable的关系

  • HashMap和Hashtable都是用于存储键和值的对应关系,都是Map的实现类,都是使用哈希表的方式存储。

  • 不同点:

    • 版本不同,Hashtable是jdk1.0版本出现的,HashMap是jdk1.2版本出现的

    • 线程安全性不同,Hashtable是线程安全的,HashMap是线程不安全的

    • Hashtable不能存储null键null值,HashMap可以存储null键null值

  • 代码示例:

  • import java.util.HashMap;
    import java.util.Hashtable;
    
    /**
     * HashMap和Hashtable的关系
     */
    public class Simple06 {
        public static void main(String[] args) {
            HashMap<String, Integer> hm = new HashMap<>();
            hm.put(null, 0);//键可以存null值
            hm.put("1", null);//值可以存null值
            // hm.put(null, null);//键值可以存null值
            System.out.println(hm);
            test1_Hashtable存储null键null值();
        }
    
        public static void test1_Hashtable存储null键null值() {
            //Hashtable 不可以存储null键值
            Hashtable<String, Integer> ht = new Hashtable<>();
            ht.put("abc", 3);
            ht.put(null, 0);
            ht.put("", null);
            ht.put(null, null);
            System.out.println(ht);
        }
    }

Collections集合工具类

  • java.utils.Collections是集合工具类,用来对集合进行操作。工具类的使用方式是类名.方法 比如Collections.sort(list)

  • 常用方法如下:

    • max

    • min

    • addAll

    • reverse

    • shuffle

    • public static void test1() {
          ArrayList<Integer> list = new ArrayList<>();
          list.add(11);
          list.add(33);
          list.add(55);
          System.out.println(Collections.max(list));
          System.out.println(Collections.min(list));
          Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8);
          System.out.println(list);
          Collections.reverse(list);
          System.out.println(list);
          Collections.shuffle(list);
          System.out.println(list);
      }

    • sort 接口实现

    • public class CollectionsUtil {
          public static void main(String[] args) {
              test2();
          }
      
          public static void test2() {
              /*
               *   java.utils.Collections是集合工具类,用来对集合进行操作。
               *   工具类的使用方式是类名.方法 比如Collections.sort(list)
               *   注意被排序的集合里面存储的元素必须要实现Comparable接口,并重写接口中
               *   的Compare To 定义排序的规则
               *   像案例中的String ,Integer 默认已经实现了Comparable接口
               *   但是如果是自定义类就需要手动实现Comparable接口并指定泛型。
               *   Compare To 定义排序的规则:
               *   this.属性 - 参数.属性 :升序 ,反之降序
               *
               * */
              ArrayList<Integer> list1 = new ArrayList<>();
              Collections.addAll(list1, 1, 44, 55, 22, 12, -45, 0);
              Collections.sort(list1);
              System.out.println(list1);// 默认升序
              ArrayList<String> list2 = new ArrayList<>();
              Collections.addAll(list2, "a", "b", "aa", "c", "bb");
              Collections.sort(list2);
              System.out.println(list2);// 默认升序
              ArrayList<Animal> list3 = new ArrayList<>();
              list3.add(new Animal("佩奇", 3));
              list3.add(new Animal("艾米丽", 5));
              list3.add(new Animal("苏西", 2));
              Collections.sort(list3);
              System.out.println(list3);
          }
      
      }
      
      class Animal implements Comparable<Animal> {
          private String name;
          private int age;
      
          public Animal(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public Animal() {
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
      // 这里不需要重写hashcode 和 equals 方法,因为我们没用set;
      
          @Override
          public String toString() {
              return "Animal{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      
          @Override
          public int compareTo(Animal o) {
              //        return this.getAge() - o.getAge();// 按年龄升序
              return o.getAge() - this.getAge();// 按年龄降序
      
          }
      }

    • sort 匿名内部类

    • public class CollectionsUtil {
          public static void main(String[] args) {
              test3();
          }
      
          public static void test3() {
              /*
               * Comparator 和 Comparable区别
               * Comparable区别是自己和别人(参数)比较,需要实现Comparable接口,重写ComparaeTo方法
               * Comparator相当于找一个第三方的裁判,比较2个参数的大小,需要使用匿名内部类
               * */
      
      
              ArrayList<Animal> list4 = new ArrayList<>();
              list4.add(new Animal("a佩奇", 3));
              list4.add(new Animal("b艾米丽", 5));
              list4.add(new Animal("a苏西", 5));
      //        Collections.sort(list4, new Comparator<Animal>() {
      //            @Override
      //            public int compare(Animal o1, Animal o2) {
      //                return o1.getAge() - o2.getAge();
      //            }
      //        });
      
              Collections.sort(list4, new Comparator<Animal>() {
                  @Override
                  public int compare(Animal o1, Animal o2) {
                      // 按年龄排序
                      int result = o1.getAge() - o2.getAge();
                      // 如果年龄相同按姓名排序
                      if (result == 0) {
                          result = o1.getName().charAt(0) - o2.getName().charAt(0);
                      }
                      return result;
                  }
              });
              System.out.println(list4);
          }
      
      }
      
      class Animal {
          private String name;
          private int age;
      
          public Animal(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public Animal() {
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
      // 这里不需要重写hashcode 和 equals 方法,因为我们没用set;
      
          @Override
          public String toString() {
              return "Animal{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Gao_xu_sheng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值