Java集合

本文详细介绍了Java中的Collection、List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)和Map(如HashMap和TreeMap)的基本概念、常用方法及底层实现机制,包括Collections工具类提供的排序和查找功能,以及线程安全性的讨论。
摘要由CSDN通过智能技术生成

集合

集合主要是两组(单列集合, 双列集合)

Collection

Vector,ArrayList,LinkedList

TreeSet,HashSet

Collection 接口有两个重要的子接口 List, Set , 他们的实现子类都是单列集合

Collection接口常用方法
add:添加单个元素
remove:删除指定元素
contains:查找元素是否存在
size:获取元素个数
isEmpty:判断是否为空
clear:清空
addAll:添加多个元素
containsAlI:查找多个元素是否都存在
removeAll:删除多个元素

Collections工具类:

介绍:

1)Collections是一个操作Set,List和Map等集合的工具类

2)Collections中提供了一系列静态的方法对集合元素进行排序

排序操作(均为static方法)
1.reverse(List):反转 List中元素的顺序
2.shuffle(List):对List 集合元素进行随机排序
3.sort(List):根据元素的自然顺序对指定List 集合元素按升序排序
4.sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
5.swap(List, int, int):将指定list 集合中的i处元素和j处元素进行交换
查找,替换
1.Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
2.Object max(Collection, Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素
3.Object min(Collection)
4.Object min(Collection,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 对象的所有旧值

List

List:

List接口 常用方法
    void add(int index, Object ele):在index位置插入ele元素;
    boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来;
    Object get(int index):获取指定index位置的元素;
    int indexOf(Object obj):返回obj在集合中首次出现的位置;
    int lastIlndexOf(Object obj):返向obj在当前集合中未次出现的位置Object ;
    remove(int index):移除指定index位置的元素,并返回此元素;
    Object set(int index, Object ele):设置指定index位者的元素为ele ,相当于是替换;
    List subList(int fromlndex, int tolndex):返回从fromIndex到tolndex位置的子集合

ArrayList的底层原理机制:

1)ArrayList中维护了一个Object类型的数组elementData.transient Object[] elementData;  //transient 表示瞬间,短暂的,表示该属性不会被序列化
2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

Vector的基本介绍:

1)Vector类的定义说明
    public class vector<E>
    extends AbstractList<E>
    implements List<E>,RandomAccess,cloneable,Serializable
2)Vector底层也是一个对象数组,protected Object[] elementData;
3)Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized
3)在开发中,需要线程同步安全时,考虑使用Vector
    
4)如果是无参构造,则初始elementData容量为10,若容量满后就按2倍扩容;如果是指定大小,则每次直接按2倍扩容。

LinkedList的全面说明:

1)LinkedList底层实现了双向链表和双端队列特点

2)可以添加任意元素(元素可以重复),包括null ​ 3)线程不安全,没有实现同步

LinkedList的底层操作机制

1)LinkedList底层维护了一个双向链表
2)LinkedList中维护了两个属性first和last分别指向首节点和尾节点
3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表
4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。    

Set

基本介绍:

1)无序(添加和取出的顺序不一致),

2)没有索引[后面演示]不允许重复元素,所以最多包含一个null

HashSet的全面说明:

  1. HashSet实现了Set接口

  2. HashSet实际上是HashMap //HashMap的底层是 数组+链表+红黑树

  3. 可以存放null值,但是只能有一个null

  4. HashSet不保证元素的有序,取决于hash后,再确定索引的结果

  5. 不能有重复的元素/对象

HashSet底层原理机制:

1)HashSet底层是HashMap
2)添加一个元素时,先得到hash值-会转成->索引值
3)找到存储数据表table,看这个索引位置是否已经存放的有元素,如果没有,直接加入,如果有,调用equals比较,如果相同,就放弃添加。如果不相同,则添加到最后
4)在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY CAPACITY(默认64).就会进行树化(红黑树)。 //table表扩容是按两倍扩
​
注意:
/*add方法里面调用put方法,该方法会执行hash(key)得到key对应的hash值,并不是直接通过hashCode()得到的,而是通过算法h = (key.hashCode()) ^ (h >>> 16)得到的*/
​
/*HashSet底层是HashMap,第一次添加时, table数组扩容到16,临界值(threshold)是16*加载因子 (loadFactor)是0.75 = 12
如果table数组使用到了临界值12,就会扩容到16* 2 =32,新的临界值就是32*0.75 = 24,依次类推*/
​
/*在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制*/
​

LinkedHashSet的全面说明:

  1. LinkedHashSet是HashSet的子类

  2. LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个数组+双向链表

  3. LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。

  4. LinkedHashSet 不允许添重复元素。

LinkedHashSet的底层机制:

1)在LinkedHastSet 中维护了一个hash表和双向链表
    (LinkedHashSet有head 和tail)
2)每一个节点有before和after属性,这样可以形成双向链表
3)在添加一个元素时,先求hash值,在求索引.确定该元素在table的位置,然后将添加的元素加入到双向链表
    (如果已经存在,不添加[原则和hashset一样])    

TreeSet:

TreeSet的底层就是TreeMap

Map

HashMap,TreeMap,HashTable,LinkedHashMap,Propertis

Map 接口的实现子类 是双列集合, 存放的K-V

Map 集合的遍历与 List 和 Set 集合不同。Map 有两组值,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。Map 以及实现 Map 的接口类(如 HashMap、TreeMap、LinkedHashMap、Hashtable 等)都可以用以下几种方式遍历。

1.在 for 循环中使用 entries 实现 Map 的遍历(最常见和最常用的)。
    public static void main(String[] argz){
        Map<String,String> map = new HashMap<String,String>() ;
        map.put("Java”,"123");
        map. put("c语言”,"123");
        for (Map.Entry<String,String> entry : map.entrySet()) {
            String mapKey = entry.getKey() ;
            String mapvalue = entry.getvalue() ;
            System.out.println(mapKey + ":" + mapvalue) ;
        }
     }           
2.使用 for-each 循环遍历 key 或者 values,一般适用于只需要 Map 中的 key 或者 value 时使用。性能上比 entrySet 较好。  
3.使用迭代器(Iterator)遍历 
                
注意,源码分析:
1)k-v最后是 HashMap$Node node = newNode(hash,key,value,null)
2)k-v为了方便础序员的遍历,还会创建 EntrySet集合,该集合存放的元素的类型Entry,而一个Entry对象就有k, v EntrySet<Entry<K,V>>即:transient Set<Hap.Entry<K,V>> entrySet;
3)entrySet中,定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node
  这是因为 static class Node<K, V> implements Map. Entry<K, V>  
4)当把 HashMap$Node 对象存放到entrySet就方便我们的遍历    

map:

map接口常用的方法:
    put:添加。
    remove:根据键删除映射关系。
    get:根据键获取值。
    size:获取元素个数。
    isEmpty:判断个数是否为0。
    clear:清除。
    containsKey:查找键是否存在。
    keySet:获取所有的键
    entrySet:获取所有关系
    values:获取所有的值    

HashMap底层机制:

1)HashMap底层维护了Node类型的数组table,默认为null
2)当创建对象时,将加载因子(loadfactor)初始化为0.75
3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换val; 如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容 调用resize()。
4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12 (16*0.75)
5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推
6)在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),粗table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
​

HashTable的基本介绍:

  1. 底层有数组Hashtable$Entry[] 初始化大小为11

  2. 第一次临界值 threshold为8 (11*0.75)

1)存放的元素是键值对:即K-V
2)hashTable的建和值都不能为null
3)hashTable使用方法基本上和HashMap一样
4)hashTable是线程安全的,hashMap是线程不安全的

Propertis基本介绍

1)Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
2)他的使用特点和Hashtable类似
3)Properties还可以用于从 xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值