• Java基础(二十三)集合(6)Map集合


      Map接口作为Java集合框架中的第二类接口,其子接口为SortedMap接口,SortedMap接口的子接口为NavigableMap接口。

      实现了Map接口具体类有:HashMap(子类LinkedHashMap)、TreeMap、EnumMap、WeakHashMap、IdentityHashMap。

      1.HashMap

      HashMap类实现了Map接口,由HashMap类实现的Map集合,允许以null作为键对象,但是因为键对象不可以重复,所以这样的键对象只能有一个。

      如果经常需要添加、删除和定位映射关系,建议利用HashMap类实现Map集合,不过在遍历集合时,得到的映射关系是无序的。

      ☆在使用由HashMap类实现的Map集合时,需要重写作为主键对象类的HashCode方法。在重写hashCode方法时,有两条基本原则:

    • 不唯一原则:不必为每个对象生成一个唯一的哈希码,只要通过hashCode方法生成的哈希码能够利用get方法得到利用put方法添加的映射关系即可。
    • 分散原则:生成哈希码的算法应尽量使哈希码的值分散一些,不要很多哈希码值都集中在一个范围内,这样有利于提高由HashMap类实现的Map集合的性能。

      在使用由HashMap类实现的Map集合时,也需要重写作为主键对象类的equals方法,该方法默认比较两个对象的地址,即使这两个键对象的内容完全相同,也不认为是同一个对象。

      (1)新建一个Map集合对象

    Map<PK_person, Person> map = new HashMap<>();

      (2)使用Map类的put方法添加一个键/值对象

            PK_person pk_person = new PK_person();
            pk_person.setPrefix("MR");
            pk_person.setNumber(13211041);
            map.put(pk_person, new Person("小一", pk_person));

      (3)使用Map类的get方法通过键得到值对象

            Person person = map.get(pk_person);
            System.out.println(person.getName() + " " + person.getNumber().getPK());

      (4)新建一个副本键对象,内容和前面的键对象完全一致,这里会打印“该键对象不存在”,这是因为虽然pk_person2和pk_person的内容完全一样,但是系统默认的equals方法比较的是两个对象的地址,而这两个对象的地址不一致,所以不认为是同一个对象。

            PK_person pk_person2 = new PK_person();
            pk_person2.setPrefix("MR");
            pk_person2.setNumber(13211041);
    
            Person person2 = map.get(pk_person2);
            if (person2==null) {
                System.out.println("该键对象不存在");
            } else {
                System.out.println(person2.getNumber().getPK());
            }

      (5)根据实际需求,如果两个键对象的内容完全一样,那么我们就应该认为这两个键对象一样,通过get方法应该能够得到映射的值对象,这个时候可以通过在键对象的类PK_person中重写hashCode方法和equals方法来解决。

      这里将默认的hashCode方法重写,从而保证了只要是键对象的内容相等,它们的hashCode码就相等。

      通过equals方法比较pk_person2和pk_person时,首先不是同一个实例、obj也不为空、是同一个类的实例,同时哈希码相等,于是判断出这两个键对象是相等的。

        // 重写hashCode方法,返回的哈希码就是简单的int类型的number加上String类型的prefix对象的hashCode方法
        @Override
        public int hashCode() {
            return number + prefix.hashCode();
        }
        
        // 重写equals方法
        @Override
        public boolean equals(Object obj) {
            if (this == obj)                            // 是否为同一个实例
                return true;
            if (obj == null)                            // 是否null
                return false;
            if (getClass() != obj.getClass())           // 是否为同一个类的实例
                return false;
            
            final PK_person other = (PK_person) obj;    // 对应的哈希码是否相同
            if (this.hashCode()!=other.hashCode())
                return false;
            return true;
        }

      然后再次运行上述程序,就可以得到对应的结果:

    MR_13211041

      完整代码:

    package hashMap.jun.iplab;
    
    public class PK_person {
    
        private String prefix;
        private int number;
        
        public String getPrefix() {
            return prefix;
        }
        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }
        public int getNumber() {
            return number;
        }
        public void setNumber(int number) {
            this.number = number;
        }
        
        public String getPK() {
            return this.prefix + "_" + this.number;
        }
        
        public void setPK(String pk) {
            int i = pk.indexOf("_");
            this.prefix = pk.substring(0, i);
            this.number = new Integer(pk.substring(i));
        }
        
        // 重写hashCode方法,返回的哈希码就是简单的int类型的number加上String类型的prefix对象的hashCode方法
        @Override
        public int hashCode() {
            return number + prefix.hashCode();
        }
        
        // 重写equals方法
        @Override
        public boolean equals(Object obj) {
            if (this == obj)                            // 是否为同一个实例
                return true;
            if (obj == null)                            // 是否null
                return false;
            if (getClass() != obj.getClass())           // 是否为同一个类的实例
                return false;
            
            final PK_person other = (PK_person) obj;    // 对应的哈希码是否相同
            if (this.hashCode()!=other.hashCode())
                return false;
            return true;
        }
        
        
    }
    PK_person
    package hashMap.jun.iplab;
    
    public class Person {
    
        private String name;
        private PK_person number;
        
        public Person(String name, PK_person number) {
            super();
            this.name = name;
            this.number = number;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public PK_person getNumber() {
            return number;
        }
    
        public void setNumber(PK_person number) {
            this.number = number;
        }
        
        
    }
    Person
    package hashMap.jun.iplab;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Test {
    
        public static void main(String[] args) {
            
            Map<PK_person, Person> map = new HashMap<>();
            
            PK_person pk_person = new PK_person();
            pk_person.setPrefix("MR");
            pk_person.setNumber(13211041);
            map.put(pk_person, new Person("小一", pk_person));
    //        Person person = map.get(pk_person);
    //        System.out.println(person.getName() + " " + person.getNumber().getPK());
            PK_person pk_person2 = new PK_person();
            pk_person2.setPrefix("MR");
            pk_person2.setNumber(13211041);
            Person person2 = map.get(pk_person2);
            if (person2==null) {
                System.out.println("该键对象不存在");
            } else {
                System.out.println(person2.getNumber().getPK());
            }
            
        }
    }
    Test

      2.TreeMap类

      TreeMap类不仅实现了Map接口,还实现了Map接口的子接口SortedMap接口。

      由TreeMap类实现的Map集合,不允许键对象为null,因为集合中的映射关系是根据键对象按照一定顺序排列的。

      在添加、删除和定位映射关系上,TreeMap类要比HashMap类的性能差一些,但是其中的映射关系具有一定的顺序,如果不需要一个有序的集合,则建议使用HashMap类;如果需要进行有序的遍历输出,则建议使用TreeMap类。

      通常的做法是:首先利用HashMap类实现一个Map集合并初始化,将元素添加到Map集合中,然后再利用TreeMap类实现一个TreeMap集合,在将原来的Map集合中的元素都添加到新的TreeMap集合中,在根据要求进行升序或者降序即可。

      TreeMap由于实现了SortedMap接口而拥有的方法为:

      

      (1)由HashMap类实现一个Map集合并将元素添加到Map集合中

            Person person1 = new Person("小一", 13311123);
            Person person2 = new Person("小二", 13223131);
            Person person3 = new Person("小三", 13432412);
            Person person4 = new Person("小四", 13621312);
            Person person5 = new Person("小五", 13531231);
            
            Map<Number, Person> map = new HashMap<>();
            map.put(person1.getId_card(), person1);
            map.put(person2.getId_card(), person2);
            map.put(person3.getId_card(), person3);
            map.put(person4.getId_card(), person4);
            map.put(person5.getId_card(), person5);

      通过遍历查看此时Map集合中的元素的排列顺序,此时没有顺序:

            Iterator<Number> it = map.keySet().iterator();
            while (it.hasNext()) {
                Number number = (Number) it.next();
                System.out.println(number);
            }
    
    输出:
    13432412
    13531231
    13223131
    13311123
    13621312

      (2)创建一个TreeMap对象,然后将原来的map集合中的数据都添加到新建的treeMap集合中,然后使用默认的排序方式即键对象的升序(Person类实现了Comparator接口)顺序进行访问

            TreeMap<Number, Person> treeMap = new TreeMap<>();
            treeMap.putAll(map);
            Iterator<Number> it_1 = treeMap.keySet().iterator();
            while (it_1.hasNext()) {
                Number number = (Number) it_1.next();
                System.out.println(number);
            }

    输出:
    13223131
    13311123
    13432412
    13531231
    13621312

      (3)新创建一个TreeMap对象,然后将原来的map集合中的数据都添加到新建的treeMap集合中,然后按照降序即反转顺序排序进行访问:

            TreeMap<Number, Person> treeMap = new TreeMap<>(Collections.reverseOrder());
            treeMap.putAll(map);
            Iterator<Number> it_1 = treeMap.keySet().iterator();
            while (it_1.hasNext()) {
                Number number = (Number) it_1.next();
                System.out.println(number);
            }
    输出:
    13621312
    13531231
    13432412
    13311123
    13223131
  • 相关阅读:
    vuejs 实战 双向数据绑定
    ubuntu16安装cuda,cudnn,gpu版opencv
    ubuntu编译安装nginx并且配置流服务器
    安装使用mongodb
    c++ 编译安装ffmpeg
    apache2 日志文件太大的解决方案
    sql注入
    制作自己的电子词典
    python传递可变参数
    工厂模式
  • 原文地址:https://www.cnblogs.com/BigJunOba/p/9408261.html
Copyright © 2020-2023  润新知