一文带你深入理解【Java基础】· Java集合(下)

news2024/9/23 7:30:46

写在前面


        Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误不足之处,请多多指正!谢谢大家!!!

        如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!


目录

写在前面

1. Map接口

1.1 Map接口概述

1.2 Map接口:常用方法

1.3 Map实现类之一:HashMap

1.4 HashMap的存储结构

1.5 HashMap源码中的重要常量

1.6 HashMap的存储结构:JDK 1.8之前

1.7 HashMap的存储结构:JDK 1.8

1.8 Map实现类之二:LinkedHashMap

1.9 Map实现类之三:TreeMap

1.10 Map实现类之四:Hashtable

1.11 Map实现类之五:Properties

1.12 Map接口代码演示

1:HashMap

2.TreeMap

3.Properties

 2. Collections工具类

2.1 Collections简介

2.2 Collections常用方法

2.3 Collections代码演示

结语


【往期回顾】

一文带你深入理解【Java基础】· Java集合(中)

一文带你深入理解【Java基础】· Java集合(上)

一文带你深入理解【Java基础】· 注解

一文带你深入理解【Java基础】· 枚举类

一文带你深入理解【Java基础】· 常用类(上)

一文带你深入理解【Java基础】· 多线程(上)


1. Map接口


1.1 Map接口概述

Map接口继承树:

  • MapCollection并列存在。用于保存具有映射关系的数据:key-value
  • Map 中的 key value 都可以是任何引用类型的数据
  • Map 中的 key Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()equals()方法
  • 常用String类作为Map的“键”
  • key value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
  • Map接口的常用实现类:HashMapTreeMapLinkedHashMap和Properties。其中,HashMapMap 接口使用频率最高的实现类


1.2 Map接口:常用方法

添加、删除、修改操作:
  • Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
  • void putAll(Map m):m中的所有key-value对存放到当前map
  • Object remove(Object key):移除指定keykey-value对,并返回value
  • void clear():清空当前map中的所有数据
元素查询的操作:
  • Object get(Object key):获取指定key对应的value
  • boolean containsKey(Object key):是否包含指定的key
  • boolean containsValue(Object value):是否包含指定的value
  • int size():返回mapkey-value对的个数
  • boolean isEmpty():判断当前map是否为空
  • boolean equals(Object obj):判断当前map和参数对象obj是否相等
元视图操作的方法:
  • Set keySet():返回所有key构成的Set集合
  • Collection values():返回所有value构成的Collection集合
  • Set entrySet():返回所有key-value对构成的Set集合

1.3 Map实现类之一:HashMap

  • HashMapMap 接口使用频率最高的实现类。
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
  • 所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
  • 一个key-value构成一个entry
  • 所有的entry构成的集合是Set:无序的、不可重复的
  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
  • HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true

1.4 HashMap的存储结构

  • JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
  • JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。


1.5 HashMap源码中的重要常量

  • DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
  • MAXIMUM_CAPACITY HashMap的最大支持容量,2^30
  • DEFAULT_LOAD_FACTORHashMap的默认加载因子
  • TREEIFY_THRESHOLDBucket中链表长度大于该默认值,转化为红黑树
  • UNTREEIFY_THRESHOLDBucket中红黑树存储的Node小于该默认值,转化为链表
  • MIN_TREEIFY_CAPACITY桶中的Node被树化时最小的hash表容量。(当桶中Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD4倍。)
  • table存储元素的数组,总是2n次幂
  • entrySet存储具体元素的集
  • sizeHashMap中存储的键值对的数量
  • modCountHashMap扩容和结构改变的次数。
  • threshold扩容的临界值,=容量*填充因子
  • loadFactor填充因子

1.6 HashMap的存储结构:JDK 1.8之前

  • HashMap的内部存储结构其实是数组和链表的结合。当实例化一个HashMap时,系统会创建一个长度为CapacityEntry数组,这个长度在哈希表中被称为容量(Capacity),在这个数组中可以存放元素的位置我们称之为“桶”(bucket),每个bucket都有自己的索引,系统可以根据索引快速的查找bucket中的元素。
  • 每个bucket中存储一个元素,即一个Entry对象,但每一个Entry对象可以带一个引用变量,用于指向下一个元素,因此,在一个桶中,就有可能生成一个Entry链。而且新添加的元素作为链表的head

添加元素的过程:

  • HashMap中添加entry1(keyvalue),需要首先计算entry1key的哈希值(根据key所在类的hashCode()计算得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i。如果位置i上没有元素,则entry1直接添加成功。如果位置i上已经存在entry2(或还有链表存在的entry3entry4),则需要通过循环的方法,依次比较entry1key和其他的entry。如果彼此hash值不同,则直接添加成功。如果hash值相同,继续比较二者是否equals。如果返回值为true,则使用entry1value去替换equalstrueentryvalue。如果遍历一遍以后,发现所有的equals返回都为false,entry1仍可添加成功。entry1指向原有的entry元素。

HashMap的扩容

  • HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize

那么HashMap什么时候进行扩容呢?

  • HashMap中的元素个数超过数组大小(数组总大小length,不是数组中个数size)*loadFactor 时 ,就会进行数组扩容 ,loadFactor的默认值(DEFAULT_LOAD_FACTOR)0.75,这是一个折中的取值。也就是说,默认情况下,数组大小(DEFAULT_INITIAL_CAPACITY)16,那么当HashMap中元素个数超过16*0.75=12(这个值就是代码中的threshold值,也叫做临界值)的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

1.7 HashMap的存储结构:JDK 1.8

  • HashMap的内部存储结构其实是数组+链表+树的结合。当实例化一个HashMap时,会初始化initialCapacityloadFactor,在put第一对映射关系时,系统会创建一个长度为initialCapacityNode数组,这个长度在哈希表中被称为容量(Capacity),在这个数组中可以存放元素的位置我们称之为“桶”(bucket),每个bucket都有自己的索引,系统可以根据索引快速的查找bucket中的元素。
  • 每个bucket中存储一个元素,即一个Node对象,但每一个Node对象可以带一个引用变量next,用于指向下一个元素,因此,在一个桶中,就有可能生成一个Node链。也可能是一个一个TreeNode对象,每一个TreeNode对象可以有两个叶子结点leftright,因此,在一个桶中,就有可能生成一个TreeNode树。而新添加的元素作为链表的last,或树的叶子结点。
那么 HashMap 什么时候进行扩容和树形化呢?
  • HashMap中的元素个数超过数组大小(数组总大小length,不是数组中个数size)*loadFactor 时 , 就会进行数组扩容 , loadFactor 的默认值(DEFAULT_LOAD_FACTOR)0.75,这是一个折中的取值。也就是说,默认情况下,数组大小(DEFAULT_INITIAL_CAPACITY)16,那么当HashMap中元素个数超过16*0.75=12(这个值就是代码中的threshold值,也叫做临界值)的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。
  • HashMap中的其中一个链的对象个数如果达到了8个,此时如果capacity没有达到64,那么HashMap会先扩容解决,如果已经达到了64,那么这个链会变成树,结点类型由Node变成TreeNode类型。当然,如果当映射关系被移除后,下次resize方法时判断树的结点个数低于6个,也会把树再转为链表。
关于映射关系的 key 是否可以修改? answer :不要修改
  • 映射关系存储到HashMap中会存储keyhash值,这样就不用在每次查找时重新计算每一个EntryNodeTreeNode)的hash值了,因此如果已经putMap中的映射关系,再修改key的属性,而这个属性又参与hashcode值的计算,那么会导致匹配不上。
总结: JDK1.8 相较于之前的变化:
  • 1.HashMap map = new HashMap();//默认情况下,先不创建长度为16的数组
  • 2.当首次调用map.put()时,再创建长度为16的数组
  • 3.数组为Node类型,在jdk7中称为Entry类型
  • 4.形成链表结构时,新添加的key-value对在链表的尾部(七上八下)
  • 5.当数组指定索引位置的链表长度>8时,且map中的数组的长度> 64时,此索引位置上的所有key-value对使用红黑树进行存储。
面试题:负载因子值的大小,对HashMap有什么影响
  • 负载因子的大小决定了HashMap的数据密度。
  • 负载因子越大密度越大,发生碰撞的几率越高,数组中的链表越容易长,造成查询或插入时的比较次数增多,性能会下降。
  • 负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建议初始化预设大一点的空间。
  • 按照其他语言的参考及研究经验,会考虑将负载因子设置为0.7~0.75,此时平均检索长度接近于常数。

1.8 Map实现类之二:LinkedHashMap

  • LinkedHashMap 是 HashMap 的子类
  • 在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

HashMap中的内部类:Node

LinkedHashMap中的内部类:Entry


1.9 Map实现类之三:TreeMap

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。
  • TreeMap 可以保证所有的 Key-Value 对处于有序状态。
  • TreeSet底层使用红黑树结构存储数据
  • TreeMap Key 的排序:
    • 自然排序TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
    • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map Key 实现Comparable 接口
  • TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0

1.10 Map实现类之四:Hashtable

  • Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
  • Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
  • HashMap不同,Hashtable 不允许使用 null 作为 key value
  • HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  • Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。

1.11 Map实现类之五:Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 keyvalue 都是字符串类型,所以 Properties 里的 key和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法


1.12 Map接口代码演示

1:HashMap

import org.junit.Test;

import java.util.*;

/**
 * 一、Map的实现类的结构:
 *  |----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
 *         |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
 *              |----LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
 *                      原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
 *                      对于频繁的遍历操作,此类执行效率高于HashMap。
 *         |----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
 *                      底层使用红黑树
 *         |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
 *              |----Properties:常用来处理配置文件。key和value都是String类型
 *
 *      HashMap的底层:数组+链表  (jdk7及之前)
 *                    数组+链表+红黑树 (jdk 8)
 *
 *  面试题:
 *  1. HashMap的底层实现原理?
 *  2. HashMap 和 Hashtable的异同?
 *  3. CurrentHashMap 与 Hashtable的异同?(暂时不讲)
 *
 *  二、Map结构的理解:
 *    Map中的key:无序的、不可重复的,使用Set存储所有的key  ---> key所在的类要重写equals()和hashCode() (以HashMap为例)
 *    Map中的value:无序的、可重复的,使用Collection存储所有的value --->value所在的类要重写equals()
 *    一个键值对:key-value构成了一个Entry对象。
 *    Map中的entry:无序的、不可重复的,使用Set存储所有的entry
 *
 *  三、HashMap的底层实现原理?以jdk7为例说明:
 *      HashMap map = new HashMap():
 *      在实例化以后,底层创建了长度是16的一维数组Entry[] table。
 *      ...可能已经执行过多次put...
 *      map.put(key1,value1):
 *      首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
 *      如果此位置上的数据为空,此时的key1-value1添加成功。 ----情况1
 *      如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据
 *      的哈希值:
 *              如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。----情况2
 *              如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
 *                      如果equals()返回false:此时key1-value1添加成功。----情况3
 *                      如果equals()返回true:使用value1替换value2。
 *
 *       补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。
 *
 *      在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。
 *
 *      jdk8 相较于jdk7在底层实现方面的不同:
 *      1. new HashMap():底层没有创建一个长度为16的数组
 *      2. jdk 8底层的数组是:Node[],而非Entry[]
 *      3. 首次调用put()方法时,底层创建长度为16的数组
 *      4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
 *         4.1 形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
 *         4.2 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,
 *         此时此索引位置上的所有数据改为使用红黑树存储。
 *
 *      DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
 *      DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
 *      threshold:扩容的临界值,=容量*填充因子:16 * 0.75 => 12
 *      TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
 *      MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64
 *
 *  四、LinkedHashMap的底层实现原理(了解)
 *      源码中:
 *      static class Entry<K,V> extends HashMap.Node<K,V> {
            Entry<K,V> before, after;//能够记录添加的元素的先后顺序
            Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
            }
        }
 *
 *   五、Map中定义的方法:
    添加、删除、修改操作:
    Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    void putAll(Map m):将m中的所有key-value对存放到当前map中
    Object remove(Object key):移除指定key的key-value对,并返回value
    void clear():清空当前map中的所有数据

    元素查询的操作:
     Object get(Object key):获取指定key对应的value
     boolean containsKey(Object key):是否包含指定的key
     boolean containsValue(Object value):是否包含指定的value
     int size():返回map中key-value对的个数
     boolean isEmpty():判断当前map是否为空
     boolean equals(Object obj):判断当前map和参数对象obj是否相等

     元视图操作的方法:
     Set keySet():返回所有key构成的Set集合
     Collection values():返回所有value构成的Collection集合
     Set entrySet():返回所有key-value对构成的Set集合

 *总结:常用方法:
 * 添加:put(Object key,Object value)
 * 删除:remove(Object key)
 * 修改:put(Object key,Object value)
 * 查询:get(Object key)
 * 长度:size()
 * 遍历:keySet() / values() / entrySet()
 */
public class MapTest {

    @Test
    public void test1() {
        Map map = new HashMap();
//        map = new Hashtable();
        map.put(null, 123);
    }

    @Test
    public void test2() {
        Map map = new HashMap();
        map = new LinkedHashMap();
        map.put(123, "AA");
        map.put(345, "BB");
        map.put(12, "CC");

        System.out.println(map);//{123=AA, 345=BB, 12=CC}
    }

    /*
     添加、删除、修改操作:
     Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
     void putAll(Map m):将m中的所有key-value对存放到当前map中
     Object remove(Object key):移除指定key的key-value对,并返回value
     void clear():清空当前map中的所有数据
     */
    @Test
    public void test3() {
        Map map = new HashMap();
        //添加
        map.put("AA", 123);
        map.put(45, 123);
        map.put("BB", 56);
        //修改
        map.put("AA", 87);

        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 key)
        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);
    }

    /*
    元素查询的操作:
     Object get(Object key):获取指定key对应的value
     boolean containsKey(Object key):是否包含指定的key
     boolean containsValue(Object value):是否包含指定的value
     int size():返回map中key-value对的个数
     boolean isEmpty():判断当前map是否为空
     boolean equals(Object obj):判断当前map和参数对象obj是否相等
     */
    @Test
    public void test4() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put(45, 123);
        map.put("BB", 56);
        // Object get(Object key)
        System.out.println(map.get(45));
        //containsKey(Object key)
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);

        isExist = map.containsValue(123);
        System.out.println(isExist);

        map.clear();

        System.out.println(map.isEmpty());
    }

    /*
    元视图操作的方法:
    Set keySet():返回所有key构成的Set集合
    Collection values():返回所有value构成的Collection集合
    Set entrySet():返回所有key-value对构成的Set集合
    */

    @Test
    public void test5() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put(45, 1234);
        map.put("BB", 56);

        //遍历所有的key集:keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println();
        //遍历所有的value集:values()
        Collection values = map.values();
        for (Object obj : values) {
            System.out.println(obj);
        }
        System.out.println();
        //遍历所有的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();
        //方式二:
        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);
        }
    }
}

2.TreeMap

public class TreeMapTest {

    //向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
    //因为要按照key进行排序:自然排序 、定制排序
    //自然排序
    @Test
    public void test1() {
        TreeMap map = new TreeMap();
        User u1 = new User("Tom", 23);
        User u2 = new User("Jerry", 32);
        User u3 = new User("Jack", 20);
        User u4 = new User("Rose", 18);

        map.put(u1, 98);
        map.put(u2, 89);
        map.put(u3, 76);
        map.put(u4, 100);

        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()) {
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
        }
    }

    //定制排序
    @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.getAge(), u2.getAge());
                }
                throw new RuntimeException("输入的类型不匹配!");
            }
        });
        User u1 = new User("Tom", 23);
        User u2 = new User("Jerry", 32);
        User u3 = new User("Jack", 20);
        User u4 = new User("Rose", 18);

        map.put(u1, 98);
        map.put(u2, 89);
        map.put(u3, 76);
        map.put(u4, 100);

        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()) {
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
        }
    }
}
public class User implements Comparable {
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("User equals()....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (age != user.age) return false;
        return name != null ? name.equals(user.name) : user.name == null;
    }

    @Override
    public int hashCode() { //return name.hashCode() + age;
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    //按照姓名从大到小排列,年龄从小到大排列
    @Override
    public int compareTo(Object o) {
        if (o instanceof User) {
            User user = (User) o;
//            return -this.name.compareTo(user.name);
            int compare = -this.name.compareTo(user.name);
            if (compare != 0) {
                return compare;
            } else {
                return Integer.compare(this.age, user.age);
            }
        } else {
            throw new RuntimeException("输入的类型不匹配");
        }
    }
}

3.Properties

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest {

    //Properties:常用来处理配置文件。key和value都是String类型
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            Properties pros = new Properties();

            fis = new FileInputStream("jdbc.properties");
            pros.load(fis);//加载流对应的文件

            String name = pros.getProperty("name");
            String password = pros.getProperty("password");

            System.out.println("name = " + name + ", password = " + password);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


 2. Collections工具类


2.1 Collections简介

  • Collections 是一个操作 SetList Map 等集合的工具类
  • Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作 (均为 static 方法)
  • reverse(List)反转 List 中元素的顺序
  • shuffle(List)List 集合元素进行随机排序
  • sort(List)根据元素的自然顺序对指定 List 集合元素按升序排序
  • sort(ListComparator)根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
  • swap(Listintint)将指定 list 集合中的 i 处元素和 j 处元素进行交换

2.2 Collections常用方法

查找、替换
  • Object max(Collection)根据元素的自然顺序,返回给定集合中的最大元素
  • Object max(CollectionComparator)根据 Comparator 指定的顺序,返回给定集合中的最大元素
  • Object min(Collection)
  • Object min(CollectionComparator)
  • int frequency(CollectionObject)返回指定集合中指定元素的出现次数
  • void copy(List dest,List src):将src中的内容复制到dest
  • boolean replaceAll(List listObject oldValObject newVal)使用新值替换List 对象的所有旧值

Collections 常用方法:同步控制
  • Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题

补充:Enumeration

  • Enumeration 接口是 Iterator 迭代器的 古老版本 

Enumeration stringEnum = new StringTokenizer("a-b*c-d-e-g", "-");
while(stringEnum.hasMoreElements()) {
    Object obj = stringEnum.nextElement();
    System.out.println(obj); 
}

2.3 Collections代码演示

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Collections:操作Collection、Map的工具类
 *
 * 面试题:Collection 和 Collections的区别?
 */
public class CollectionsTest {

    /*
    reverse(List):反转 List 中元素的顺序
    shuffle(List):对 List 集合元素进行随机排序
    sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

    Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
    Object min(Collection)
    Object min(Collection,Comparator)
    int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    void copy(List dest,List src):将src中的内容复制到dest中
    boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
    */
    @Test
    public void test1() {
        List list = new ArrayList();
        list.add(123);
        list.add(43);
        list.add(765);
        list.add(765);
        list.add(765);
        list.add(-97);
        list.add(0);

        System.out.println(list);

//        Collections.reverse(list);
//        Collections.shuffle(list);
//        Collections.sort(list);
//        Collections.swap(list,1,2);
        int frequency = Collections.frequency(list, 123);

        System.out.println(list);
        System.out.println(frequency);
    }
    @Test
    public void test2() {
        List list = new ArrayList();
        list.add(123);
        list.add(43);
        list.add(765);
        list.add(-97);
        list.add(0);

        //报异常:IndexOutOfBoundsException("Source does not fit in dest")
        //List dest = new ArrayList();
        //Collections.copy(dest,list);//此时dest数组长度为0,小于list数组
        //正确的:
        List dest = Arrays.asList(new Object[list.size()]);
        System.out.println(dest.size());//list.size();
        Collections.copy(dest, list);

        System.out.println(dest);

        /*
        Collections 类中提供了多个 synchronizedXxx() 方法,
        该方法可使将指定集合包装成线程同步的集合,从而可以解决
        多线程并发访问集合时的线程安全问题
         */
        //返回的list1即为线程安全的List
        List list1 = Collections.synchronizedList(list);
    }
}


结语


本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/57461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pikachu靶场全关攻略(超详细!)

一、靶场搭建 准备工具 phpstudy**pikachu靶场下载地址&#xff1a;**https://github.com/zhuifengshaonianhanlu/pikachu 搭建过程 将靶场文件夹放到phpstudy的www目录 进入pikach文件夹的inc目录&#xff0c;修改靶场配置文件config.inc.php&#xff0c;设置数据库账号密…

Ubuntu 安装 Zotero, 并导入原有数据库,然后同步账户

文章目录写在前面一、下载 Linux 下的 Zotero二、安装Zotero三、导入自己的数据库三、同步账户参考链接写在前面 发文时间&#xff1a;2022.12.03 自己的系统是Ubuntu20.04.5&#xff0c;Zotero 是 Zotero-6.0.18_linux-x86_64.tar.bz2 一、下载 Linux 下的 Zotero 直接登录…

魔兽世界开服教程——魔兽世界服务器架设全攻略---战网+Ladder排行版

需要用到的软件&#xff1a; 1. WAMP5 v1.7.exe &#xff08;这个是为排行榜提供数据库服务&#xff0c;为Mysql数据库&#xff09; 2.PvPGN-1.8.2-0-Win32-MySQL-5.0.45-BIN.zip PvPGN-1.8.2-0-Win32-SQLite-3.5.1-BIN.zip &#xff08;这三个是战网主文件&#xff09; pvpgn-…

使用dos命令符操作,感光屏绘图,ccd摄像头采集图像,并按程序进行机械加工的计算机

使用dos命令符操作&#xff0c;感光屏绘图&#xff0c;ccd摄像头采集图像&#xff0c;并按程序进行机械加工的计算机 使用dos命令符操作&#xff0c;感光屏绘图&#xff0c;ccd摄像头采集图像&#xff0c;并按程序进行机械加工的计算机是一种可以按照dos命令符复制磁带程序&…

yolov1算法思想流程简单讲解概述————(究极简单的讲述和理解)

在我想学习算法的时候&#xff0c;我看某些大佬特别喜欢上来就讲论文&#xff0c;给我搞的贼难受&#xff0c;毕竟本人太辣鸡了&#xff0c;上来这么搞看不懂&#xff0c;经过诸多算法的这样折磨。我打算根据自己的亲身经历和学习过程中遇到的问题出一期&#xff0c;先讲算法整…

智能优化算法(源码)—蜣螂优化算法(Dung beetle optimizer,DBO)

获取更多资讯&#xff0c;赶快关注上面的公众号吧&#xff01; 文章目录启发数学模型滚球跳舞繁殖觅食偷窃伪代码2022年11月27日&#xff0c;东华大学沈波教授团队&#xff0c;继麻雀搜索算法之后&#xff0c;又提出了一种全新的群体智能优化算法——蜣螂优化&#xff08;Dung …

功率信号源在超声波及智能骨料损伤监测中的应用

实验名称&#xff1a;超声波及智能骨料损伤监测原理 研究方向&#xff1a;无损检测、损伤定位 实验原理&#xff1a;换能器所产生的高频信号在介质中传播遇到裂缝、空洞等缺陷产生反射、折射、绕射等现象到达接收端时大量衰减&#xff0c;声学参量发生一定的变化&#xff0c;基…

ABAP学习笔记之——第七章:ABAP数据字典

一、数据字典 在 ABAP 程序里使用的所有对象 (表、视图、结构体、类型等)统称为 ABAP 数据字典。这些对象的信息叫 Metadata 或者 Data Definition&#xff0c;另外&#xff0c;ABAP 数据字典有定义和管理数据结构&#xff0c;集中管理系统中使用的对象的功能。 数据字典类型&…

Spring框架(五):SpringAop底层原理和注解配置

SpringAop底层原理和注解配置引子Aop简介利用Aop原理实现一个Demo&#xff08;代理模式&#xff09;Aop的xml方式实现Aop的注解方式实现总结引子 痛定思痛&#xff0c;主要问题出现在自己雀氏不熟悉框架底层、一些面试题&#xff0c;以及sql的一些情况淡忘了。 本章节的开始是…

[附源码]计算机毕业设计学生疫情防控信息填报系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【信号去噪】基于变分贝叶斯卡尔曼滤波器实现信号滤波附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

安卓APP源码和设计报告——智能垃圾桶

课程名称&#xff1a; 移动互联网应用开发 实验名称&#xff1a; 姓名/学号&#xff1a; 专业/班级&#xff1a; 指导教师&#xff1a; 实验时间&#xff1a; 一、案例功能需求 该系统是了解垃圾分类以及物品查询属于哪类垃圾的智能化APP。该系统可以实现用户登陆注册&a…

[附源码]计算机毕业设计JAVA校园摄影爱好者交流网站

[附源码]计算机毕业设计JAVA校园摄影爱好者交流网站 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM …

Web大学生网页作业成品 基于HTML+CSS+JavaScript个人简历介绍 学生个人网站作业设计代做 学生个人网页设计作品

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【历史上的今天】12 月 3 日:世界上第一条短信;Fortran 语言之父诞生;百度贴吧上线

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2022 年 12 月 3 日&#xff0c;在 21 年前的今天&#xff0c;电动平衡车&#xff08;Segway&#xff09;问世&#xff1b;电动平衡车是一种电力驱动、具有自我平衡能力…

教师教学质量评价管理系统(ASP.net+SqlServer)

目录 摘 要 I Abstract II 目录 III 第一章 引言 1 1.1 课题的背景和意义 1 1.2 教学质量评价信息系统的发展 1 1.2.1 国外主要教育评价方法 1 1.2.2我国高校教师教学评价的发展 2 第二章 开发技术简介 3 2.1 .NET框架简介 3 2.2 ASP.NET简介 4 2.3 SQL Server 2008数据库 5 第…

Cinema 4D初学者终极指南

Cinema 4D初学者终极指南 通过此 Cinema 4D 课程将您的设计技能提升到一个新的水平&#xff0c;进入 3rd Dimension 课程英文名&#xff1a;Cinema 4D Masterclass The Ultimate Guide for Beginners 此视频教程共5.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印…

[附源码]Python计算机毕业设计Django面包连锁店管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

北京一互联网公司被端,所有开发被全部带走!

△Hollis, 一个对Coding有着独特追求的人△这是Hollis的第 407 篇原创分享作者 l Hollis来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09;近日&#xff0c;北京市朝阳公安分局对外公开&#xff0c;按照公安部“净网”专项行动整体部署&#xff0c;朝阳警方深入…

视觉SLAM十四讲ch4笔记——李群与李代数

文章目录视觉SLAM十四讲ch4——李群与李代数4.1 李群李代数基础4.2 指数映射和对数映射4.2.1 so(3)↔SO(3)so(3) \leftrightarrow SO(3)so(3)↔SO(3)4.2.2 se(3)↔SE(3)se(3) \leftrightarrow SE(3)se(3)↔SE(3)4.2.3 小总结&#xff1a;so(3)↔SO(3)so(3) \leftrightarrow SO(…