Java-List& Set& Map

92 篇文章 0 订阅
16 篇文章 0 订阅

ArrayList / LinkedList / Vector特点及比较

ArrayList特点:

  1. 线程不安全
  2. 底层使用 Object[]存储
  3. 实例化时默认10个元素
  4. 插入(添加到元素与元素之间)和删除的操作效率很差
  5. 值加到末尾, 查询和遍历操作性能很好

LinkedList特点:

  1. 线程不安全
  2. 底层使用双向链表存储
  3. 插入(添加到元素与元素之间)和删除的操作效率很好

Vector特点:

  1. 线程安全
  2. 底层使用 Object[]存储
  3. 实例化时默认10个元素

* 由于性能原因, 现在基本不再使用 Vector, 即使需要线程安全也不会使用. 如需要则通过 ArrayList结合 Collections工具类中的 synchronizedList方法来实现


	List list = Collections.synchronizedList(new ArrayList<>());
        list.add(2);
        list.add(4);
        list.add(1);
        synchronized (list) {
            Iterator i = list.iterator();
            while (i.hasNext()) {
                System.out.println(i.next());
            }
        }

  • ArrayList& Vector的区别:
  1. 两种集合实例化时, 都默认生成10个元素. 区别为 Vector(jdk7& 8)是会直接开辟10个元素(类似于单例的饿汉式), 而 ArrayList(jdk8)是只会赋予 {}, 也就是未直接开辟10个元素的内存空间当添加新值时才会真正创建数组(类似于单列的懒汉式), 不过 ArrayList(jdk7)也是直接开辟
  2. 每当扩容时 Vector是默认2倍, 而 ArrayList是1.5倍(原有长度 + (原有长度 >> 1 向右移一位等同除以2))
  • 基本使用

	ArrayList arrayList = new ArrayList();
        arrayList.add(2);
        arrayList.add(4);
        arrayList.add(1);
        arrayList.add(1, 100); // 插入
        System.out.println(arrayList); // [2, 100, 4, 1]

        arrayList.set(2, 200); // 覆盖
        System.out.println(arrayList); // [2, 100, 200, 1]

        arrayList.addAll(1, Arrays.asList(300, 400)); // 插入
        System.out.println(arrayList); // [2, 300, 400, 100, 200, 1]

        arrayList.addAll(Arrays.asList(new int[] {111, 222})); // 当一个元素添加
        System.out.println(arrayList); // [2, 300, 400, 100, 200, 1, [I@1540e19d]

        arrayList.addAll(Arrays.asList(new Integer[] {333, 444})); // 按多个元素添加
        System.out.println(arrayList); // [2, 300, 400, 100, 200, 1, [I@1540e19d, 333, 444]

	System.out.println(arrayList.indexOf(400)); // 2
	System.out.println(arrayList.lastIndexOf(999)); // -1
	System.out.println(arrayList.subList(1, 3)); // [300, 400]

        arrayList.remove(2); // 指定索引
        System.out.println(arrayList); // [2, 300, 100, 200, 1, [I@1540e19d, 333, 444]

        arrayList.remove(new Integer(2)); // 指定值, 不是索引
        System.out.println(arrayList); // [300, 100, 200, 1, [I@1540e19d, 333, 444]

	# 迭代器
        Iterator iter = arrayList.iterator();
        while(iter.hasNext()) {
            System.out.println(iter.next());
        }

	300
	100
	200
	1

Map

  • Map是用来保存有映射关系的数据(key-value), key和 value可以是任何引用类型的数据

HashMap / LinkedHashMap / TreeMap / Hashtable / Properties特点及比较

HashMap特点:

  1. 线程不安全
  2. key是用 Set来存放的, 即存储是无序的, 且不可重复(当 key为自定义 Java类, 且要按照属性的值来判断是否相等, 则需要覆写 equals方法和 hashCode方法)
  3. 可以存 null键& 值
  4. 键的存储是无序的
  5. 键不可重复
  6. 底层数组长度超过了临界值, 且要存放的位置非空时, 便会自动扩容(默认2倍)
  7. 自定义初始长度必须是2的多少次幂, 如: 设置了15, 会自动被改为16
  • Jdk7及以前版本的特点:
    (1) 实例化时默认创建16的一维数组类型 Entry[] table
    (2) 存储结构是数组+链表: 当哈希冲突时
    (-) 如果 Key相同, 则覆盖 value
    (-) 会生成链表, 新 key存到数组的指定位置, 然后将之前的值(key)往下移存到链表中(存到链表的首个节点)
  • Jdk8较于之前的变化:
    (1) 实例化时不会(默认)直接创建长度为16的数组, 而是在首次调用 put方法时, 便会真正创建16的数组 Node[] tab
    (2) 存储结构是数组+链表+红黑树: 当哈希冲突时
    (-) 如果 Key相同, 则覆盖 value
    (-) 会生成链表, 将新 key存到链表中(存到链表的最后节点)
    (-) 当数组的某一个索引位置上元素以链表形式存的数据个数已达到8个, 且当前数组长度已达到64时, 此索引位置上的所有数据会被变更为红黑树存储结构(数组长度小于64, 则会自动扩容)
    (-) 当有映射关系被移除时, 内部 Resize方法, 会判断树的节点个数是否低于6个, 如果低于, 则会将红黑树再转换为链表存储结构
  1. 什么是负载因子? 负载因子决定 HashMap的数据密度(DEFAULT_LOAD_FACTOR=0.75f)
    (-) 密度越大, 发生碰撞的几率就越高, 数组中的链表会越长.
    (-) 密度越小, 发生碰撞的几率就越小, 数组中的链表会越短, 就越容易触发扩容
  2. 什么是吞吐临界值? threshold=32(当前容量)*0.75f(负载因子/DEFAULT_LOAD_FACTOR)
    (-) 触发自动扩容的界限值
    (-) 为什么 HashMap元素未填满就会扩容? 因为所有元素不一定能填满, 可能很多部分 key会一直发生碰撞产生链表和红黑树
  • 基本使用

        HashMap hashMap = new HashMap();
        hashMap.put("A", 11);
        hashMap.put("C", 33);
        hashMap.put("B", 22);
        hashMap.put("D", 44);
        Object return01 = hashMap.remove("C"); // 删除并返回值
        System.out.println(return01); // 33
        boolean return02 = hashMap.containsKey("B"); // 是否包含指定键
        System.out.println(return02); // true
        boolean return03 = hashMap.containsValue(33); // 是否包含指定键
        System.out.println(return03); // false
        Set return04 = hashMap.keySet(); // 返回所有 key构成的 Set集合
        System.out.println(return04); // [A, B, D]
        Collection return05 = hashMap.values(); // 返回所有 value构成的 Collection集合
        System.out.println(return05); // [11, 22, 44]
        Set return06 = hashMap.entrySet(); // 返回所有 key-value对构成的 Set集合
        System.out.println(return06); // [A=11, B=22, D=44]

LinkedHashMap特点:

  1. HashMap的子集
  2. 采用了哈希表和链表(双向链表)的结合, 随是存储无序, 但是遍历时是按插入的顺序输出

TreeMap特点:

  1. 根据 key进行排序
  2. Key不能为 null
  3. 存储是有序
    (1) 自然排序: 值为自定义类时, 实现 Comparable接口, 覆写 compareTo方法
    (2) 定制排序: 实现 Comparator接口, 定制排序条件; new TreeSet(new Comparator() {public int compare}), 当两种都有时, 会优先采用定制排序
  4. 底层结构是红黑树的存储结构
  5. 查询速度比 List快

Hashtable特点:

  1. 线程安全
  2. 不可以存 null键& 值
  3. 其它与 HashMap基本相同

* 由于性能原因, 现在基本不再使用 Hashtable, 即使需要线程安全也不会使用. 如需要则通过 HashMap结合 Collections工具类中的 synchronizedMap方法来实现或者使用 CurrentHashMap

Properties特点:

  1. Hashtable的子集, 继承了 Hashtable的基本特性 如 线程安全等
  2. Key和 value都是 String类型
  • 演示代码

	Properties pros = new Properties();
        pros.load(new FileInputStream("jdbc.properties"));
        String user = pros.getProperty("user");
        System.out.println(user);

HashSet / LinkedHashSet / TreeSet特点及比较

HashSet特点:

  1. 线程不安全
  2. 可以存 null值
  3. 存储是无序的(无序不等于随机, 当存储数据时, 会使用 HashCode+算法计算下标来存到底层数组中)
  4. 不可重复的(值为自定义 Java类, 且要按照属性的值来判断是否相等, 则需要覆写 equals方法和 hashCode方法)
  5. 底层结构是 HashMap(实例化默认长度& 扩容机制等: 参考 HashMap)

LinkedHashSet特点:

  1. 作为 HashSet的子集, 基本特性 如: 线程不安全, 存 null值, 存储无序, 不可重复等相同
  2. 底层结构是 LinkedHashMap, 采用了哈希表和链表(双向链表)的结合, 随是存储无序, 但是遍历时是按插入的顺序输出
  3. 遍历效率高于 HashSet

TreeSet特点:

  1. 线程不安全
  2. 不能存 null值
  3. 不可重复
  4. 底层结构是 TreeMap, 基本特点相同

Collections工具类

  • 基本使用

        List<Integer> list = new ArrayList<>();
        list.add(2);
        list.add(3);
        list.add(1);
        Collections.reverse(list); // 反转 List中的元素顺序
        System.out.println(list); // [1, 3, 2]
        Collections.sort(list); // 自然顺序: 将 List集合元素按升序排序
        // Collections.sort(list, Comparator); 定制排序
        System.out.println(list); // [1, 2, 3]
        Collections.swap(list, 2, 0); // 将指定 List集合中的 i处元素和 j处元素进行交换
        System.out.println(list); // [3, 2, 1]
        // Collections.shuffle(list); // 对 List集合元素进行随机排序
        // System.out.println(list);
        System.out.println(Collections.max(list)); // 返回指定集合中的最大元素
        // System.out.println(Collections.max(list, Comparator)); 返回最大元素(指定条件)
        System.out.println(Collections.min(list)); // 返回指定集合中的最小元素
        // System.out.println(Collections.min(list, Comparator)); // 返回最小元素(指定条件)

        list.add(2);
        list.add(2);
        System.out.println(list); // [3, 2, 1, 2, 2]
        System.out.println(Collections.frequency(list, 2)); // 返回指定集合中指定元素的出现次数

        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest, list); // 将 list(src)中的内容复制到 dest中
        System.out.println(dest.size()); // 5

        Collections.replaceAll(dest, 2, 4); // 将指定 List对象的所有旧值(oldVal), 替换为新值(newVal)
        System.out.println(dest); // [3, 4, 1, 4, 4]

如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值