zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    防删没什么意思啊,直接写废你~
    绝大多数情况下,没有解决不了的问题,只有因为平时缺少练习而惧怕问题的复杂度,畏惧的心理让我们选择避让,采取并不那么好的方案去解决问题
    Java 模拟面试题
    Crossthread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on
    一步步从数据库备份恢复SharePoint Portal Server 2003
    【转】理解 JavaScript 闭包
    Just For Fun
    The database schema is too old to perform this operation in this SharePoint cluster. Please upgrade the database and...
    Hello World!
    使用filter筛选刚体碰撞
  • 原文地址:https://www.cnblogs.com/BigJunOba/p/9408261.html
Copyright © 2011-2022 走看看