20210323Java集合

Java集合

编辑时间:2021/03/23

读完本节:大概花费40钟,共3530词

1.集合Collection中存储自定义对象的注意事项
  1. 对于List存储自定义对象需要重写equals()方法,删除元素、修改元素、插入元素时需要用到自定义类中的equals()方法确定是否存在元素,然后才是执行操作
  2. 对于Set分两种情况:
    1. 对于Set的HashSet、LinkedHashSet实现类,需要重写equals()、hashCode()方法,原因同上。
    2. 对于Set的TreeSet实现类,需要实现Comparable接口中的compareTo(Object obj)或者Comparator接口中的compare(Object o1, Object o2)
2.Java集合之Map接口
  1. Map接口继承树:

    image-20210323160920293

  2. Map接口:存储双列数据,存储的时key-value对的数据。

  3. Map接口有三个实现类:HashMap、TreeMap、Hashtable。

  4. HashMap有一个子类LinkedHashMap底层使用链表方式支持;Properties是Hashtable的一个子类,其key和value都是String类型

  5. HashMap的底层,在JDK1.7及之前运用了数组+链表;在JDK1.8后运用数组+链表+红黑树

  6. Map中的key是无序的、不可重复的,使用Set从存储所有的key,key所在的类需要重写equals()方法和hashCode()方法;Map中的value也是无序的,但可以重复,使用Collection存储所有的value,同样的value所在的类也需要重equals()方法;一个key-value键值对构成了一个Entry对象;Map中的Entry是无序的、不可重复的,使用Set存储所有的Entry

  7. Map接口常用的方法:

    1. 添加、删除、修改操作:

      1. Object put(Object key, Object value):将指定的key-value添加到(或修改)到当前map对象中

      2. void putAll(Map m):将m中所有的key-value键值对存放到当前Map中

      3. Object remove(Object key):移除指定key的key-value键值对,并返回value

      4. void clear():清空当前map中的所有数据

        import org.junit.Test;
        
        import java.util.HashMap;
        import java.util.Map;
        
        /**
         * @Author: xuehai.XUE
         * @MailBox: xuehai.xue@qq.com
         * @Date: 2021/3/23 19:32
         * @Description:
         */
        public class MapMethodTest {
        
            @Test
            public void test(){
                //因为Map是一个接口,其中定义的方法都是抽象方法,
                //因此通过实现类HashMap来展示Map中定义的功能
                Map map = new HashMap();
        
                //添加
                map.put("AA",123);
                map.put(456,123);
                map.put("BB",567);
                //修改
                map.put("AA",97);
        
                System.out.println(map);
        
                Map map1 = new HashMap();
                map1.put("CC",123);
                map1.put("DD",123);
        
                map.putAll(map1);
        
                System.out.println(map);
        
        
                //remove(Object obj)
                Object value = map.remove("CC");
                System.out.println(value);
                System.out.println(map);
        
                //clear()
                map.clear();//与map = null操作不同
                System.out.println(map.size());
                System.out.println(map);
            }
        }
        
    2. 元素查询操作:

      1. Object get(Object key):获取指定key对应的value

      2. boolean containsKey(Object key):是否包含指定的key

      3. boolean containsValue(Object value):是否包含指定的Value

      4. int size():返回map中key-value键值对的个数

      5. boolean isEmpty():判断当前map是否为空

      6. boolean equals(Object obj):判断当前map和参数对象obj是否相等

        import org.junit.Test;
        
        import java.util.HashMap;
        import java.util.Map;
        
        /**
         * @Author: xuehai.XUE
         * @MailBox: xuehai.xue@qq.com
         * @Date: 2021/3/23 19:32
         * @Description:
         */
        public class MapMethodTest {
        
            @Test
            public void test1(){
                Map map = new HashMap();
                map.put("AA",123);
                map.put(456,123);
                map.put("BB",567);
        
                //找到返回value没找到返回null
                System.out.println(map.get(456));
            }
        }
        
    3. 元视图的操作方法:

      1. Set keySet():返回所有key构成的Set集合

      2. Collection values():返回所有value构成的Collection集合

      3. Set entrySet():返回所有key-value键值对的构成的Set集合

        import org.junit.Test;
        
        import java.util.*;
        
        /**
         * @Author: xuehai.XUE
         * @MailBox: xuehai.xue@qq.com
         * @Date: 2021/3/23 19:32
         * @Description:
         */
        public class MapMethodTest {
        
            @Test
            public void test2(){
                Map map = new HashMap();
                map.put("AA",123);
                map.put(456,123);
                map.put("BB",567);
        
                //遍历所有的key集
                Set set = map.keySet();
                Iterator iterator = set.iterator();
                while(iterator.hasNext()){
                    System.out.println(iterator.next());
                }
        
                System.out.println("*****************");
        
                //遍历所有的value集
                Collection values = map.values();
                //方式1:采用增强for循环
                for(Object obj : values){
                    System.out.println(obj);
                }
        
                //遍历所有的key-value
                //方式一:使用entrySet()
                Set entrySet = map.entrySet();
                Iterator iterator1 = entrySet.iterator();
                while (iterator1.hasNext()){
                    Object obj = iterator1.next();
                    //entrySet集合中的元素都是entry
                    Map.Entry entry = (Map.Entry) obj;
                    System.out.println(entry.getKey() + "----" + entry.getValue());
                }
        
                System.out.println("*****************");
        
                //使用keySet和values配合完成遍历所有的key-value
                Set keySet = map.keySet();
                Iterator iterator2 = keySet.iterator();
                while (iterator2.hasNext()){
                    Object key = iterator2.next();
                    Object value = map.get(key);
                    System.out.println(key + "====" + value);
                }
            }
        }
        
    4. Map常用方法小结:

      1. 添加:put(Object key, Object value)
      2. 删除:remove(Object key)
      3. 修改:put(Object key, Object value)
      4. 查询:get(Object key)
      5. 长度:size()
      6. 遍历:keySet() / values() / entrySet()
3.Map实现类之HashMap
  1. HashMap是Map接口中使用频率最高的实现类
  2. HashMap允许使用null键和null值,与HashSet一样的是,HashMap不能保证映射的顺序
  3. 所有的key构成的集合是Set,这个Set集合是无序的、不可重复的。所以key所在的类要重写:equals()方法和hashCode()方法
  4. 所有的value构成的集合是Collection,这个Collection是无序的、可以重复的。所以value所在的类要重写:equals()方法
  5. 一个键值对构成一个entry,所有的entry构成的集合Set是无序的、不可重复的
  6. HashMao判断两个key相等的标准是:两个key通过equals返回true,且hashCode值也相等
  7. HashMap判断两个value相等的标准是:两个value通过equals()方法返回true
  8. HashMap虽然是线程不安全的,但是提高了效率
4.HashMap底层实现原理
  1. 在JDK1.7中和JDK1.8中HashMap底层实现原理略有不同

  2. HashMap的底层实现原理(JDK1.7环境下):

    1. HashMap的实例化过程:

      HashMap map = new HashMap()
      

      在实例化完成后,底层创建了一个长度是16的一维数组Entry[] table

    2. 图示HashMap添加元素的过程:

      image-20210323165440782

      对于第第二个和第三个判断,其中的key1-value1和原来的数据以链表的方式存储

    3. HashMap在元素的添加过程中,底层数组的扩容机制

      在向HashMap中不断添加数据的过程中,会涉及扩容问题,当超出临界值(且要存放的位置非空时)扩容为原来容量的两倍(resize(newCapacity * table.length)),并将原有的数据复制到新的Entry[] table数组中。

    4. HashMap底层源码(JDK1.7)

      image-20210323170832227

      image-20210323170904625

      image-20210323171013819

      image-20210323171100026

      image-20210323171145072

      image-20210323171219336

      image-20210323171344066

      image-20210323171428998

  3. HashMap在JDK1.8中与JDK1.7中底层实现原理的差异

    1. new HashMap():实例化HashMap时,底层没有立刻实例化一个长度为16的数组

    2. 在JDK1.8中,底层数组使用的时Node[] 而非Entry[]

    3. 在首次调用HashMap的put方法时,底层才创建一个长度为16的Node[]数组

    4. JDK1.7底层结构只有:数组+链表;JDK1.8底层结构是:数组+链表+红黑树

      1. 当满足数组的某一个索引位置上的元素以链表形式存在的数据个数,即链表长度超过8;且当前数组的长度大于64时,此时索引位置上的所有数据改为使用红黑树存储
    5. JDK1.8环境下HashMap的底层源码

      image-20210323183932217

      image-20210323183959561

      image-20210323184039223

      image-20210323184135057

      image-20210323184159872

      image-20210323184241325

      image-20210323184357111

      image-20210323184423365

      image-20210323184610538

5.HashMap中重要的常量
  1. DEFAULT_INITIAL_CAPACIRY:HashMap的默认容量16
  2. MAXIMUM_CAPACIRY:HashMap最大支持容量1^30
  3. DEFAULT_LOAD_FACTOR:HashMap默认加载因子 0.75
  4. TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,则将链表转换为红黑树 8
  5. UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转换为链表
  6. MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。64(当桶中Node的数量大到需要转换为红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行resize扩容操作,这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍)
  7. table:存储元素的数组,总是2的n次幂
  8. entrySet:存储具体元素的集
  9. size:HashMap中存储的键值对的数量
  10. modCount:HashMap扩容和改变结构的次数
  11. threshold:扩容的临界值,等于“容量*填充因子”
  12. loadFactor:填充因子
6.HashMap子类LinkedHashMap
  1. LinkedHashMap中定义的内部类与HashMap中定义的内部类不同,HashMap中定义的内部类是Node,LinkedHashMap定义的内部类是Entry,LinkedHashMap定义的Entry内部类,它与HashMap不同的是LinkedHashMap维护了一个贯穿其所有条目的双向链表。这个链表定义了遍历顺序,通常是插入map中的顺序
  2. LinkedHashMap继承于HashMap,实现了Map接口,重写了父类HashMap中的newNode方法
  3. 对于频繁的遍历操作,此类执行效率高于HashMap,但是其他的操作(直接向数组中插入元素等)HashMap的效率要更高
7.LinkedHashMap底层实现先后顺序的原理
  1. image-20210323192713954

    其中的before和after用于记录添加元素的先后顺序

8.HashSet在底层添加元素时的过程
  1. image-20210323193003179

    HashSet在底层添加元素时,实际上是将元素放入HashMap中的一个key中,且该key指向的是一个Object对象

    image-20210323193140364

9.Map实现类之TreeMap
  1. 保证按照添加的key-value对进行排序,实现遍历排序,此时需要考虑实现Comparable接口中的compareTo(Object obj)方法,或者实现Comparator中的compare(Object o1, Object o2)方法,即考虑key的自然排序或者定制排序;TreeMap底层采用红黑树实现

    import org.junit.Test;
    
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.TreeMap;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/23 20:02
     * @Description:
     */
    public class TreeMapTest {
    
        /** 定制排序 */
        @Test
        public void test2(){
            TreeMap map = new TreeMap(new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    if(o1 instanceof User && o2 instanceof User){
                        User u1 = (User)o1;
                        User u2 = (User)o2;
                        return -Integer.compare(u1.getId(),u2.getId());
                    }
                    throw new RuntimeException("输入的类型不匹配!");
                }
            });
    
            User u1 = new User("Genji", 1);
            User u2 = new User("Hana", 2);
            User u3 = new User("Zenyatta", 3);
            User u4 = new User("Maccree", 4);
            User u5 = new User("Ashe", 5);
    
            map.put(u1,200);
            map.put(u2,500);
            map.put(u3,200);
            map.put(u4,200);
            map.put(u5,200);
    
            Set set = map.keySet();
    
            Iterator iterator = set.iterator();
            while(iterator.hasNext()){
                System.out.println(iterator.next());
            }
        }
    
        /** 自然排序 */
        @Test
        public void test1(){
            TreeMap map = new TreeMap();
            User u1 = new User("Genji", 1);
            User u2 = new User("Hana", 2);
            User u3 = new User("Zenyatta", 3);
            User u4 = new User("Maccree", 4);
            User u5 = new User("Ashe", 5);
    
            map.put(u1,200);
            map.put(u2,500);
            map.put(u3,200);
            map.put(u4,200);
            map.put(u5,200);
    
            Set set = map.keySet();
    
            Iterator iterator = set.iterator();
            while(iterator.hasNext()){
                System.out.println(iterator.next());
            }
    
        }
    }
    
    import java.util.Objects;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/22 19:05
     * @Description:
     */
    public class User implements Comparable{
        private String name;
        private int id;
    
        public User() {
    
        }
    
        public User(String name, int id) {
            this.name = name;
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    '}';
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof User)) return false;
            User user = (User) o;
            return getId() == user.getId() &&
                    Objects.equals(getName(), user.getName());
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(getName(), getId());
        }
    
        /** 输入的性名按照从大到小的顺序排列 */
        @Override
        public int compareTo(Object o){
            if(o instanceof User){
                User user = (User)o;
                return -this.name.compareTo(user.name);
            }else{
                throw new RuntimeException("输入的类型不匹配");
            }
        }
    }
    
10. Map实现类之Properties
  1. Properties是Hashtable的子类,该对象用于处理属性文件

  2. 由于属性文件里的key、value都是字符串类型,所以Properties里的key和value都是字符串类型

  3. 存取数据时,通常使用setProperty(String key, String value)方法和getProperty(String key)方法

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.Properties;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/23 20:23
     * @Description:
     */
    public class PropertiesTest {
        public static void main(String[] args) {
            Properties pro = new Properties();
            FileInputStream fis = null;
    
            try {
                fis = new FileInputStream("jdbc.properties");
                pro.load(fis);
    
                String name = pro.getProperty("name");
                String pwd = pro.getProperty("password");
    
                System.out.println("name = " + name + ", password = " + pwd);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(fis != null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    name=biggy
    password=962469
    
11.HashMap、TreeMap、Hashtable三者的区别
  1. HashMap:作为Map的主要实现类;线程不安全,但效率高;能够存储null值的key和value;底层在JDK1.7采用数组+链表,JDK1.8采用数组+链表+红黑树
  2. TreeMap:保证按照添加键值对的顺序进行排序,实现排序遍历;底层的比较不使用equals()方法和hashCode()方法,而是实现Comparable接口中的compareTo(Object obj)方法,或实现Comparator中的compare(Object o1, Object o2)方法。
  3. Hashtable:作为古老的Map实现类,虽然线程安全,但是效率低;不能存储null值的key和value
12.Collections工具类
  1. 类似于Arrays工具类,Collections是一个操作List、Set和Map等集合的工具类

  2. Collections中提供了一系列的静态方法,这些方法可以对集合元素进行排序、查询、和修改等操作

  3. 常用操作:

    1. 排序操作(均为static):

      1. reverse(List):反转List中的元素
      2. shuffle(List):对List集合元素进行随机排序
      3. sort(List):根据元素的自然顺序对指定List集合元素按升序排列
      4. sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
      5. swap(List, int i, int j):将指定List集合中的i处元素和j处元素进行交换
    2. 查找、替换

      1. Object max(Collection):根据元素的自然排序,返回指定集合中最大的元素
      2. Object min(Collection):根据元素的自然排序,返回指定集合中最小的元素
      3. Object max(Collection, Comparator):根据Comparator指定的顺序,返回给定集合中最大的元素
      4. Object min(Collection, Comparator):根据Comparator指定的顺序,返回给定集合中最小的元素
      5. int frequency(Collection, Object):返回指定集合中指定元素出现的频率(次数)
      6. void copy(List dest, List src):将src中的内容复制到dest中
      7. boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象中所有的旧值
    3. 同步控制

      1. Collections类中提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题(ArrayList、LinkedArrayList、HashSet、LinkedHashSet、HashMap、LinkedHashMap等)
      import org.junit.Test;
      
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.Collections;
      import java.util.List;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/23 20:58
       * @Description:
       */
      public class CollectionsTest {
          @Test
          public void test(){
              List list = new ArrayList();
              list.add(123);
              list.add(451);
              list.add(485);
              list.add(0);
              list.add(-516);
              list.add(98);
      
              System.out.println(list);
      
              //报异常:java.lang.IndexOutOfBoundsException: Source does not fit in dest
      //        List dest = new ArrayList();
      
              //正确写法:创建相同长度的null值List dest
              List dest = Arrays.asList(new Object[list.size()]);
              System.out.println(dest);
      
              Collections.copy(dest, list);
      
              System.out.println(dest);
      
              //返回的list1即为线程安全的list
              List list1 = Collections.synchronizedList(list);
      
          }
      }
      

image-20210303180846928

STAY ANGER!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值