`

java_集合体系之Map体系总结(二)

 
阅读更多

3.3、 LinkedHashMap

3.31 LinkedHashMap特点:

Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此链接列表定义了迭代顺序(即存储的顺序与输出的顺序相同),该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。此实现不是同步的

注意

①当key为String或基本数据类型包装类,键相同自动替换旧值为新值 (因为他们已重写了hashCode与equals方法)
②当key为自定义对象,需让其重写hashCode与equals方法才能保证key的唯一性

3.32 LinkedHashMap使用示例

public class LinkedHashMapReview {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
    }

    /**
     * 自定义对象为key
     * 需让其重写hashCode与equals方法才能保证key的唯一性
     */
    private static void test3() {
        LinkedHashMap<Info, Integer> map=new LinkedHashMap<Info, Integer>();
        map.put(new Info(0, "vvv"), 000);
        map.put(new Info(0, "vvv"), 333);
        map.put(new Info(1, "ccc"), 111);
        System.out.println(map);
        // output :  当Info没有重写hashCode与equals方法,
//      {Info [id=0, adress=vvv]=0, Info [id=0, adress=vvv]=333, Info [id=1, adress=ccc]=111}

        // output :  当Info重写hashCode与equals方法
//      {Info [id=0, adress=vvv]=333, Info [id=1, adress=ccc]=111}

    }

    /**
     * 基本数据类型包装类重写了hashCode与equals方法,键相同自动替换旧值为新值
     */
    private static void test2() {
        LinkedHashMap<Integer, Integer> map=new LinkedHashMap<Integer, Integer>();
        map.put(1, 66);
        map.put(2, 67);
        map.put(3, 68);
        map.put(1, 69);  // 自动装箱 Integer.valueOf(69)
        System.out.println(map);
        // output
//      {1=69, 2=67, 3=68}
        // 输出顺序与存储相同,重复添加已有的键会替换掉旧值
    }

    /**
     * String做key
     * String类实现了hashCode与equals方法,键相同自动替换旧值为新值
     */
    private static void test1() {
        LinkedHashMap<String, String> map=new LinkedHashMap<String, String>();
        map.put("aa", "121");
        map.put("bb", "122");
        map.put("cc", "123");
        map.put("aa", "122");
        map.put("dd", "122");
        map.put("ee", "122");

        System.out.println(map);
        // output 
        // {aa=122, bb=122, cc=123, dd=122, ee=122}
        // 输出顺序与存储相同,重复添加已有的键会替换掉旧值
    }
}

3.4、 Hashtable

Hashtable是同步的,它不允许使用 null 值和 null 键。除此之外与HashMap大致相同,示例略 

3.41 使用Properties

Properties类继承自Hashtable,表示了一个持久的属性集,由键值对(key-value)组成。

与Hashtable不同的是,Properties 属性列表中每个键及其对应值都是一个字符串,因此不推荐使用Hashtable的put方法为Properties添加属性。

Properties 可通过store方法保存在流中或通过load方法从流中加载。如下三种方式:

1.通过字节输入输出流

 void load(InputStream inStream) 
                  从输入流中读取属性列表(键和元素对)。 
 void store(OutputStream out, String comments) 
                  以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 

2.通过字符输入输出流

 void load(Reader reader) 
              按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
void store(Writer writer, String comments) 
              以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 

3.通过xml

void loadFromXML(InputStream in) 
              将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中。   
void storeToXML(OutputStream os, String comment) 
              发出一个表示此表中包含的所有属性的 XML 文档。 
void storeToXML(OutputStream os, String comment, String encoding) 
              使用指定的编码发出一个表示此表中包含的所有属性的 XML 文档。  

通过如下方法存取键值

 String getProperty(String key) 
              用指定的键在此属性列表中搜索属性。 
String getProperty(String key, String defaultValue) 
              用指定的键在属性列表中搜索属性。 
 Object setProperty(String key, String value) 
              调用 Hashtable 的方法 put。 

 void list(PrintStream out) 
              将属性列表输出到指定的输出流。 
 void list(PrintWriter out) 
              将属性列表输出到指定的输出流。 
 Set<String> stringPropertyNames() 
              返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。 

下面通过示例使用Properties
1.创建一个属性文件

/**
     * 创建一个属性文件
     * @throws IOException
     */
    private static void create() throws IOException {
        // 创建一个空的属性文件
        Properties prop = new Properties();
        // 创建一个文件输出流,用于写出属性文件到本地
        FileWriter writer = new FileWriter("config.properties");//亦可以使用FileOutputStream
        // 设置属性键与值
        prop.setProperty("name", "pecuyu");
        prop.setProperty("character", "kind");
        // 通过字符输出流将键值对写入属性文件
        prop.store(writer, "this is new");
        writer.close();
    }

2.读取属性文件内容

    /**
     * 读取一个属性文件
     */
    private static void load() throws FileNotFoundException, IOException {
        // 创建属性文件
        Properties prop=new Properties();
        // 从流中读取属性列表到属性文件
        prop.load(new FileInputStream("config.properties"));// 亦可使用FileReader
        // 通过键取值
        String name = prop.getProperty("name");
        String character = prop.getProperty("character");
        //System.out.println("name="+name+" character="+character);

        prop.list(System.out); // 将属性键值对列出并打印到控制台

        Set<String> stringPropertyNames = prop.stringPropertyNames();// 键的set集合
        for (String key : stringPropertyNames) {
            String value = prop.getProperty(key);  // 通过键获取值
            System.out.println("key="+key+" value="+value);
        }

    }

3.5、 WeakHashMap

3.51 特点

以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。 
null 值和 null 键都被支持

3.52 实现注意事项

WeakHashMap 中的值对象由普通的强引用保持。因此应该小心谨慎,确保值对象不会直接或间接地强引用其自身的键,因为这会阻止键的丢弃。注意,值对象可以通过 WeakHashMap 本身间接引用其对应的键;这就是说,某个值对象可能强引用某个其他的键对象,而与该键对象相关联的值对象转而强引用第一个值对象的键。处理此问题的一种方法是,在插入前将值自身包装在 WeakReferences 中,如:m.put(key, new WeakReference(value)),然后,分别用 get 进行解包。 

3.6、 TreeMap

3.61 TreeMap特点

- 基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
- 键值对是红黑树结构,可以保证键的排序和唯一性
- 此实现不是同步的

须为TreeMap提供排序方案

①根据其键的自然顺序进行排序(自定义对象须实现Comparable接口并重写compare方法)
②根据创建映射时提供的Comparator进行排序,具体取决于使用的构造方法。

3.62 分析TreeMap的put方法源码

1、判断Entry是否有元素,没有则new一个,并添加新元素
2、通过自然排序与比较器排序来为TreeMap排序,优先使用Comparator来排序

通过Entry对象来来确保插入元素的唯一性,它建立在compare方法的基础上,此方法返回0时,表示插入的键存在,直接替换旧值并返回。因此在使用TreeMap时,自定义对象须实现Comparable接口并重写compare方法或在创建TreeMap时提供Comparator
    cmp = cpr.compare(key, t.key);
     if (cmp < 0)
          t = t.left;
      else if (cmp > 0)
          t = t.right;
      else
      return t.setValue(value);

3、在插入元素后重新调整红黑树(即Entry树)

源码如下

public V put(K key, V value) {
        Entry<K,V> t = root;
        // 判断Entry是否有元素,没有则new一个
        if (t == null) {
         compare(key, key); // type (and possibly null) check
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null; 
        }
        int cmp;
        Entry<K,V> parent;
        // 通过自然排序与比较器排序
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

3.63 TreeMap使用示例

public class TreeMapReview {
    public static void main(String[] args) {
        test1();
        test2();
    }

    /**
     * 自定义对象做key,需满足以下两个条件之一,否则抛出异常java.lang.ClassCastException:com.yu.bean.Info cannot be cast to java.lang.Comparable
     * ①实现Comparable接口并重写compare方法
     * ②构造TreeMap对象时,需传入Comparator
     * 当两者都有,以Comparator来排序
     */
    private static void test2() {
        TreeMap<Info, String> map=new TreeMap<Info, String>(new Comparator<Info>() {
            @Override
            public int compare(Info o1, Info o2) {
                int num = o2.getId() - o1.getId();
                num = num == 0 ? o2.getAdress().hashCode() - o1.getAdress().hashCode() : num;
                return num;
            }
        });
        map.put(new Info(000, "hhh"), "qqq");
        map.put(new Info(001, "hhh"), "aaa");
        map.put(new Info(002, "hhh"), "zzz");
        map.put(new Info(000, "hhh"), "qqq");

        System.out.println(map);
    }

    /**
     * String类型或基本类型包装类做key
     * String类实现了Comparable接口,可以进行自然排序
     */
    private static void test1() {
        TreeMap<String, String> map = new TreeMap<String, String>();
        map.put("a", "111");
        map.put("b", "123");
        map.put("c", "121");
        map.put("c", "121");

        Set<Entry<String, String>> entrySet = map.entrySet();
        for (Entry<String, String> entry : entrySet) {
            System.out.println("key=" + entry.getKey() + " value="
                    + entry.getValue());
        }
        // output:
//      key=a value=111
//      key=b value=123
//      key=c value=121
    }
}
分享到:
评论

相关推荐

    java集合体系结构完结篇-Map集合

    java集合体系结构完结篇-Map集合

    Java-Java集合体系-List-Set

    Java-Java集合体系-List-Set 内容概要:总结了Java集体体系中的三大集合接口LIst、Set、Map,本文对LIst、Set做出了详细、简要的分析,没有冗长的文章,全是干货,下载即用,其中涉及了其底层实现,面试题必备。 ...

    java集合体系思维脑图

    java集合体系思维脑图,主要介绍了map、conllection、juc集合

    【Java】Java集合框架思维导图。

    xmind格式的Java集合框架学习导图,包括Collection接口/Map接口以及具体实现类。 同样包含大厂面试题,也在导图中有所体现。 能学到什么: 更加成体系的知识框架,更加全面的、系统的知识。 思维导图: 思维导图具有...

    实验05 Java集合.doc

    掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet、TreeSet) 3)了解List接口及主要实现类(ArrayList、LinkedList、Vector) 4)了解Map接口及主要实现类(HashMap、TreeMap、...

    JAVA–集合

    集合按照其存储结构可以分为两大类,单列集合java.util.Collection、双列集合java.util.Map 一、Collection Collection集合框架的体系 Collection常用功能 1.public boolean add(E e):把给定的对象添加到集合中 2....

    Java 基础核心总结 +经典算法大全.rar

    -、Iterator Iterable ListIterator 二、Map 和 Collection 接口Map 集合体系详解 HashMap LinkedHashMap TreeMap WeakHashMap Hashtable Collection 集合体系详解 Set 接口 AbstractSet 抽象类SortedSet 接口...

    集合xmind整理(分为List、Set、Queue和Map四种体系)

    集合的xmind整理图。Java集合大致可分为List、Set、Queue和Map四种体系.List:代表有序、重复的集合。 Set:代表无序、不可重复的集合。 Map:则代表具有映射关系的集合。

    Java集合

    Java的集合类是一种特别有用的工具类,它可以用于存储数量不等的多个对象,并可以实现常用数据结构,如栈,队列等,除此之外,Java集合还可用于保存具有映射关系的关联数组。 Java的集合大致上可分为:Set,List和...

    超全Java集合框架讲解.md

    - Map 集合体系详解 - HashMap - LinkedHashMap - TreeMap - WeakHashMap - Hashtable - Collection 集合体系详解 - Set 接口 - AbstractSet 抽象类 - SortedSet 接口 - HashSet - LinkedHashSet - ...

    实验七:Java集合与泛型

    本次实验掌握了集合的概念、体系结构、分类及使用场景,了解了Set接口及主要实现类(HashSet、TreeSet),了解了解List接口及主要实现类(ArrayList、LinkedList、Vector),掌握ArrayList的使用及其与Vector的区别,...

    JAVA集合框架

    集合框架是一个统一的架构,负责保存、装载数据...JAVA结合框架可以分为set、list、map、queue四大体系,其中set代表无序不可重复的集合;list代表有序、可重复的集合;map代表具有映射关系的集合;queue代表队列集合。

    java笔记整理(超详细) java笔记整理(超详细)

    Java集合可以分为Collection和Map两种体系: Collection接口: ​ List:元素有序,可重复的集合 ​ ArrayList: 底层数组实现,有利于随机访问get ​ LinkedList:底层是链表,有利于频繁的插入、删除操作(ArrayList删除和...

    毕业就业-刷题库Java面试题大全(2021年-2022年).rar

    二、Java集合容器面试题 1、集合容器概述 2、Collection接口 3、Map接口 4、辅助工具类 三、Java异常面试题 1. Error 和 Exception 区别是什么? 2. 运行时异常和一般异常(受检异常)区别是什么? 3. JVM 是如何处理...

    JAVA基础课程讲义

    异常的处理办法之二,声明异常: throws子句 101 方法重写中声明异常原则 102 异常的处理办法之三,手动抛出异常,throw子句 103 自定义异常 103 使用异常机制建议 104 总结 105 思考作业 105 上机作业 105 第五章 ...

    新版java教程 全套javase零基础到高级视频教程小白自学编程下载地址

    ,重点讲解Collection:集合框架体系List/Set/Map多种 实现和API ·玩转集合框架迭代器和HashCode和Equals重新排序 实战 ·实战teratori迭代器和自定义Comparable:排序接口 ·玩转ava操作文件File类常用操作 ·案例...

    Java语音学习,基础教程

    学习集合:理解Java中的Collection、泛型、List、Set、Collections、Map和HashMap等概念和用法。 掌握异常处理:了解Java的异常体系、异常分类,学会声明、抛出和捕获异常,并自定义异常。 初步掌握多线程:理解线程...

    java初学者必看

    最近正在学习Java,也买了很多的有关Java方面的书籍,其中发现《跟我学Java》这本书,都的很不错啊,所以顺便拿电脑把这本书的目录敲了下来,与大家分享。尤其是那些和我一样初学Java的朋友们,看看哪一节对你有用,...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    java基础案例与开发详解案例源码全

    11.1 Java集合框架概述264 11.2 Collection接口264 11.2 Set接口实现类266 11.2.1 实现类HashSet267 11.2.2 实现类LinkHashSet270 11.2.3 实现类TreeSet272 11.3 List接口实现类277 11.3.1 实现类ArrayList277 ...

Global site tag (gtag.js) - Google Analytics