java 常用集合list与Set、Map区别及适用场景总结

3.1、集合与数组的区别,缓存的管理,Collection 、List、Set 接口的作用及相关的子类

在这里插入图片描述

3.1.2、Collection 接口

Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。

public interface Collection<E> extends Iterable<E> 

在这里插入图片描述
在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。

3.1.3、List 接口

1、List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
2、List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
3、JDK API中List接口的实现类常用的有:ArrayList(95%使用)、LinkedList和Vector。

List的实现类

1、ArrayList:底层实现是数组,线程不安全,效率高,所以,查询块,修改、插入、删除慢
2、LinkedList:底层实现是链表,线程不安全,效率高。所以,查询慢,修改、插入、删除快
3、Vector:底层实现是数组,线程安全,效率低。但是即使为保证 List 集合线程安全,也不推荐使用Vector。

ArrayList的JDK1.8之前与之后的实现区别?
JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组

Vector 类和 ArrayList 类的区别(重点)

在这里插入图片描述
1、底层都是数组,Vector默认初始容量是10,ArrayList看版本.
2、ArrayList扩容增加原来的50%,Vector扩容增加原来的1倍。
3、ArrayList线程不安全,效率高,Vector线程安全,效率低。
4、Vector因为版本古老,支持Enumeration 迭代器。但是该迭代器不支持快速失败。而Iterator和ListIterator迭代器支持快速失败。

链表操作类:LinkedList(理解)

在这里插入图片描述

3.1.4、Set 接口(重点)

1、Set接口是Collection的子接口,set接口没有提供额外的方法。
2、Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
3、Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法。因此存放到Set集合中的元素一定要注意equals方法的重写。

Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。

散列存放:HashSet(重点)

1、HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
2、HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
3、HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
4、HashSet 具有以下特点:
①不能保证元素的排列顺序 ②HashSet 不是线程安全的 ③集合元素可以有一个是 null
结论:存放到Set集合中的元素一定要注意equals和hashcode方法的重写。

有序LinkedHashSet

1、LinkedHashSet 是 HashSet 的子类
2、 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
3、LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
4、LinkedHashSet 不允许集合元素重复。

TreeSet

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。

自然排序:

实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。

定制排序:

TreeSet的自然排序是根据集合元素的大小,进行元素升序排列。如果需要定制排序,比如降序排列,可通过Comparator接口的帮助。需要重写compare(T o1,T o2)方法。利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

Collection集合框架集

在这里插入图片描述

集合输出:Iterator(绝对重点)

概念:Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出。
1、Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
2、因为Collection接口继承了Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
3、Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。
在这里插入图片描述
在这里插入图片描述
注意:在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator 接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。

Collection<String> all = new ArrayList<String>();
	Iterator<String> iter = all.iterator();
	while (iter.hasNext()) {// 判断是否有下一个元素
		String str = iter.next(); // 取出当前元素
		if (str.equals("C")) {
		all.remove(str); // 错误的,调用了集合中的删除
		iter.remove(); // 正确删除,调用迭代器删除
	} else {
		System.out.print(str + "、");
	}
}

3.2、Map 接口(重点)

在这里插入图片描述

以上的 Collection 中,每次操作的都是一个对象,如果现在假设要操作一对对象,则就必须使用 Map 了

public interface Map<K,V>

此接口与 Collection 接口没有任何的关系,是第二大的集合操作接口。此接口常用方法如下
在这里插入图片描述

HashMap(重点)

public class HashMap<K,V> extends AbstractMap<K,V> 
implements Map<K,V>, Cloneable, Serializable

此类继承了 AbstractMap 类,同时可以被克隆,可以被序列化下来。

1、HashMap 判断两个 key 相等的标准是:
两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
2、HashMap 判断两个 value相等的标准是:
两个 value 通过 equals() 方法返回 true。
3、HashMap线程不安全

put方法原理

在这里插入图片描述

 /**
     * Implements Map.put and related methods.
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length; //1、resize默认长度为16,散列因子0.75f
        if ((p = tab[i = (n - 1) & hash]) == null) //2、(n - 1) & hash取模运算
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            //如果哈希值相等,就覆盖
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // 如果表中已经存在该key,就覆盖掉
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
HashMap的扩容

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

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

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

Map其他子类介绍

2、LinkedHashMap

LinkedHashMap 是 HashMap 的子类
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

3、TreeMap

TreeMap存储 Key-Value 对时,需要根据 key进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。

4、Hashtable

Hashtable是个古老的 Map 实现类,线程安全。
与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
Hashtable判断两个key相等、两个value相等的标准,与hashMap一致。

5、Properties

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值