Java集合Map常用子类简介

Map(映射,存储的是“键-值”映射表,“键”是不能重复的)

如果键重复,则相当于修改对应键的值。

Map接口定义方法

    int size();//获取map大小

    boolean isEmpty();//size==0?

    boolean containsKey(Object var1);//查看是否包含某个键

    boolean containsValue(Object var1);//查看是否包含某个值

    V get(Object var1);//跟据key获取值

    V put(K var1, V var2);//Map接口有两个类型参数,K和V,分别表示键(Key)和值(Value)的类型,按Key值var1保存值var2,如果键重复,则相当于修改对应键的值。

    V remove(Object var1);//移除键对应的值

    void putAll(Map<? extends K, ? extends V> var1);//批量保存

    void clear();//清空map

    Set<K> keySet();//获取Map中键的集合

    Collection<V> values();//获取Map中值的集合

    Set<Map.Entry<K, V>> entrySet();//获取Map中值的键值对(遍历)

    public interface Entry<K, V> {
            K getKey();//键

            V getValue();//值

            V setValue(V var1);//修改键

            boolean equals(Object var1);

            int hashCode();

        }

方法使用简介(以HashMap实现类为例)

HashMap 存储的数据是没有顺序的,键或值可以为null

    /**
     * Map
     */
    public class Demo {

        public static void main(String[] args) {
            //key   //value//Map<K,V>
            Map<Integer, String> map = new HashMap<>();
            map.put(1, "aaa");//添加元素
            map.put(2, "www");
            map.put(3, "assaa");
            map.put(4, "qqq");
            map.put(5, "ggg");
            map.put(1, "nnn");//修改元素
            map.put(6, "ooo");
            map.put(7, "232");
            map.put(12, "ffds");
            System.out.println(map.size() + "");//获取大小//8
            //////////////////////
            System.out.println(map.isEmpty());//size==0?//false
            //////////////////////
            System.out.println(map.containsKey(10));//查看是否包含某个键//false
            /////////////////////
            System.out.println(map.containsValue("ooo"));//查看是否包含某个值//true
            /////////////////////
            System.out.println(map.get(3));//跟据key获取值//assaa
            /////////////////////
            map.remove(12);//移除键对应的值
            System.out.println(map.containsKey(12));//false
            /////////////////////
            Map<Integer, String> map1 = new HashMap<>();
            map.put(100, "999");//添加元素
            map.put(110, "222");//添加元素
            map.put(120, "333");//添加元素
            map.putAll(map1);//批量保存
            Set<Integer> integers = map.keySet();//获取Map中键的集合
            System.out.println(integers);//[1, 2, 3, 4, 100, 5, 6, 7, 120, 110]
            ////////////////////////
            Collection<String> values = map.values();//获取Map中值的集合
            System.out.println(values);//[nnn, www, assaa, qqq, 999, ggg, ooo, 232, 333, 222]
            ////////////////////////
            Set<Map.Entry<Integer, String>> entries = map.entrySet();//迭代
            Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map.Entry<Integer, String> mapNext = iterator.next();
                System.out.print(mapNext.getKey() + "-->" + mapNext.getValue() + "\t");
                //1-->nnn   2-->www 3-->assaa   4-->qqq 100-->999   5-->ggg 6-->ooo 7-->232 120-->333   110-->222
            }

        }
    }
额外延伸SparseArray

Hashtable

Hashtable和HashMap的区别
  • Hashtable里面的方法几乎都是同步的,线程安全,HashMap则没有,但效率高。(同ArrAyList和Vector)
  • Hashtable不允许存放null值(键和值都不可以),而HashMap可以
相同点
  • 存放元素无序

LinkedHashMap继承自HashMap

  • LinkedHashMap 实现与 HashMap 的不同之处在于,LinkedHashMap 维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,
    该迭代顺序可以是插入顺序或者是访问顺序(参考以下代码理解)
  • 不是线程安全

案例

      /**
       * LinkedHashMap
       * LinkedHashMap和HashMap区别
       * LinkedHashMap 保存了记录的插入顺序
       * HashMap 则无序存放
       */
      public class Demo {
          public static void main(String[] args) {
              //关注点一:看添加之后的输出结果对比
              System.out.println("关注点一:LinkedHashMap输出:");
              LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap();
              linkedHashMap.put(1, "aaa");//添加元素
              linkedHashMap.put(7, "www");
              linkedHashMap.put(5, "ggg");
              linkedHashMap.put(1, "nnn");//修改元素
              linkedHashMap.put(6, "ooo");
              linkedHashMap.put(7, "232");
              linkedHashMap.put(12, "ffds");
              Set<Map.Entry<Integer, String>> entries = linkedHashMap.entrySet();
              Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
              while (iterator.hasNext()) {
                  Map.Entry<Integer, String> next = iterator.next();
                  System.out.print(next.getKey() + "-->" + next.getValue() + "\t");
                  //1-->nnn 7-->232 5-->ggg 6-->ooo 12-->ffds
              }
              System.out.println();
              System.out.println("关注点一:HashMap输出:");
              Map<Integer, String> map = new HashMap<>();
              map.put(1, "aaa");//添加元素
              map.put(7, "www");
              map.put(5, "ggg");
              map.put(1, "nnn");//修改元素
              map.put(6, "ooo");
              map.put(7, "232");
              map.put(12, "ffds");
              Set<Map.Entry<Integer, String>> entries1 = map.entrySet();//迭代
              Iterator<Map.Entry<Integer, String>> iterator1 = entries1.iterator();
              while (iterator1.hasNext()) {
                  Map.Entry<Integer, String> mapNext = iterator1.next();
                  System.out.print(mapNext.getKey() + "-->" + mapNext.getValue() + "\t");
                  //1-->nnn 5-->ggg 6-->ooo 7-->232 12-->ffds
              }
              /////////////////////////////////////////////////////////////////
              //关注点二:换一个构造方法
              System.out.println();                                              //10 大小//0.75还不清楚//true代表使用访问顺序
              LinkedHashMap<Integer, String> linkedHashMap1 = new LinkedHashMap<>(10, 0.75f, true);
              linkedHashMap1.put(1, "aaa");//添加元素
              linkedHashMap1.put(7, "www");
              linkedHashMap1.put(5, "ggg");
              linkedHashMap1.put(1, "nnn");//修改元素
              linkedHashMap1.put(6, "ooo");
              linkedHashMap1.put(7, "232");
              linkedHashMap1.put(12, "ffds");
              System.out.println("=======================================================");
              System.out.println("更换构造方法后未使用元素之前输出");
              Set<Map.Entry<Integer, String>> entries2 = linkedHashMap1.entrySet();
              Iterator<Map.Entry<Integer, String>> iterator2 = entries2.iterator();
              while (iterator2.hasNext()) {
                  Map.Entry<Integer, String> next = iterator2.next();
                  System.out.print(next.getKey() + "-->" + next.getValue() + "\t");
                  //5-->ggg 1-->nnn 6-->ooo 7-->232 12-->ffds
              }
              System.out.println();
              //关键点来了
              System.out.println(linkedHashMap1.get(6));//ooo
              System.out.println(linkedHashMap1.get(12));//ffds
              System.out.println("更换构造方法后未使用元素之后输出");
              Set<Map.Entry<Integer, String>> entries3 = linkedHashMap1.entrySet();
              Iterator<Map.Entry<Integer, String>> iterator3 = entries3.iterator();
              while (iterator3.hasNext()) {
                  Map.Entry<Integer, String> next = iterator3.next();
                  System.out.print(next.getKey() + "-->" + next.getValue() + "\t");
                  //5-->ggg 1-->nnn 7-->232 6-->ooo 12-->ffds
              }
          }
      }

运行结果:

LinkedHashMap延伸(用途)

最近最少使用LRUcache
最近最少使用LRUcache
最近最少使用LRUcache
最近最少使用LRUcache

TreeMap

使用了二叉权的数据结构,key是有序,保存其唯一性用到了hashCode()、equals()以及比较器(唯一性判断,键排序同TreeSet)
案例
    /**
     * TreeMap:
     * 使用了二叉权的数据结构,key是有序,保存其唯一性用到了hashCode()、equals()以及比较器(唯一性判断同HashSet)
     */
    public class Demo {
        public static void main(String[] args) {
            //来个稍微复杂点的:存放一个Student链表
            //TreeMap<K,V>K类必须实现Comparable<T>接口,用于比较排序
            TreeMap<String, List<Student>> map = new TreeMap<>();
            List<Student> students1 = new ArrayList<>();
            students1.add(new Student("小花", 23));
            students1.add(new Student("小黑", 20));
            students1.add(new Student("小鱼", 29));
            students1.add(new Student("小小", 23));
            map.put("小班", students1);
            List<Student> students2 = new ArrayList<>();
            students2.add(new Student("大花", 230));
            students2.add(new Student("大黑", 200));
            students2.add(new Student("大鱼", 290));
            students2.add(new Student("大大", 230));
            map.put("大班", students2);
            Set<Map.Entry<String, List<Student>>> entries = map.entrySet();
            for (Map.Entry<String, List<Student>> entry : entries) {
                List<Student> s = entry.getValue();
                System.out.println(entry.getKey() + ":" + s);
            }
        }
    }
    class Student {
        private String name;
        private int age;
        public Student(String name, int age) {
            this.age = age;
            this.name = name;
        }
        @Override
        public String toString() {
            return "[" + this.name + ":\t" + this.age + "]";
        }
    }
运行结果

案例二

    /**
     * TreeMap自定义比较器
     * <p>
     * 案例:按地区存放学校
     * 建模
     * //School
     * //Area
     */
    public class Demo {
        public static void main(String[] args) {
            List<School> schools1 = new ArrayList<School>();
            schools1.add(new School("10", "火星1"));
            schools1.add(new School("11", "火星2"));
            schools1.add(new School("12", "火星3"));
            List<School> schools2 = new ArrayList<School>();
            schools2.add(new School("20", "北京1"));
            schools2.add(new School("21", "北京2"));
            schools2.add(new School("22", "北京3"));  
            //如果TreeMap<K,V>的K是自定义类型 ,则此类必须实现Comparable<T>接口,用于比较排序
            Map<Area, List<School>> clsMap = new TreeMap<Area, List<School>>();
            clsMap.put(new Area("1004", "火星"), schools1);
            clsMap.put(new Area("1002", "北京"), schools2);
            Set<Map.Entry<Area, List<School>>> entrySet = clsMap.entrySet();
            for (Map.Entry<Area, List<School>> cls : entrySet) {
                List<School> s = cls.getValue();
                System.out.println(cls.getKey().id+"\t" + cls.getKey().name + ":" + s);
            }
        }
    }
    //
    class Area implements Comparable<Area> {
        //名字
        String name;
        //编号
        String id;
        public Area(String id, String name) {
            this.id = id;
            this.name = name;
        }   
        @Override
        public int compareTo(Area o) {
            //先比较班级的名称,如果名称相同,再比较id(也可以先比较id再比较name)
            int r = this.name.compareTo(o.name);
            return r == 0 ? this.id.compareTo(o.id) : r;
        }
        @Override
        public String toString() {
            return this.name + "\t";
        }
    }
    class School {
        private String id;
        private String name;
        public School(String id, String name) {
            this.id = id;
            this.name = name;
        }
        @Override
        public String toString() {
            return "School[id=" + id + ", name=" + name + "]";
        }
    }
运行结果

补充

List、Set、Map是否继承自Collection接口?

List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

阐述ArrayList、Vector、LinkedList的存储性能和特性。

ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。Vector属于遗留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用

Collection和Collections的区别?

Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等

List、Map、Set三个接口存取元素时,各有什么特点?

List以特定索引来存取元素,可以有重复元素。Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容