java各种集合

参考:https://www.jianshu.com/p/047e33fdefd2

1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。

2、Set(无序、不能重复)
Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。

 

参考:https://github.com/helen-x/AndroidInterview/blob/master/java/%5BJava%5D%20%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E7%9A%84%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%E5%92%8C%E4%BD%BF%E7%94%A8%E8%A7%84%E5%88%99%E6%A2%B3%E7%90%86.md


java相关集合

 

 

java.util.concurrent 包添加了多个新的线程安全集合类(ConcurrentHashMap、CopyOnWriteArrayList 和CopyOnWriteArraySet)这些类的目的是提供高性能、高度可伸缩性、线程安全的基本集合类型版本

通过同步的封装工厂(Collections.synchronizedMap()、synchronizedList() 和 synchronizedSet()),非线程安全集合均可表现为线程安全的
 

 

Vector、ArrayList、LinkedList

    Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集合,并且可以随机地访问其中的元素。  
   Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。  


    ArrayList和LinkedList区别  
    1. ArrayList是实现了基于动态数组数据结构,而LinkedList是基于链表的数据结构;

        2. 对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;

       3. 对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢,下面会详细分析。

 

 

 

HashTable,HashMap,HashSet
HashTable和HashMap采用相同的存储机制,二者的实现基本一致,不同的是:


1)、HashMap是非线程安全的,HashTable是线程安全的,内部的方法基本都是synchronized。


2)、HashTable不允许有null值的存在。


在HashTable中调用put方法时,如果key为null,直接抛出NullPointerException。其它细微的差别还有,比如初始化Entry数组的大小等等,但基本思想和HashMap一样。


HashSet:
1、HashSet基于HashMap实现,无容量限制。
2、HashSet是非线程安全的。 
3、HashSet不保证有序。 


HashMap:
1、HashMap采用数组方式存储key,value构成的Entry对象,无容量限制。
2、HashMap基于Key hash查找Entry对象存放到数组的位置,对于hash冲突采用链表的方式来解决。
3、HashMap在插入元素时可能会要扩大数组的容量,在扩大容量时须要重新计算hash,并复制对象到新的数组中。
4、HashMap是非线程安全的。
5、HashMap遍历使用的是Iterator 


HashTable
1、HashTable是线程安全的。
2、HashTable中无论是Key,还是Value都不允许为null。
3、HashTable遍历使用的是Enumeration。 


TreeSet,TreeMap
 TreeSet:
 1、TreeSet基于TreeMap实现,支持排序。
 2、TreeSet是非线程安全的。


    从对HashSet和TreeSet的描述来看,TreeSet和HashSet一样,也是完全基于Map来实现的,并且都不支持get(int)来获取指定位置的元素(需要遍历获取),另外TreeSet还提供了一些排序方面的支持。例如传入Comparator实现、descendingSet以及descendingIterator等。


TreeMap: 
1、TreeMap是一个典型的基于红黑树的Map实现,因此它要求一定要有Key比较的方法,要么传入Comparator实现,要么key对象实现Comparable接口。

 

2、TreeMap是非线程安全的。

 

 

 

主要区别

 

Vector和ArrayList
1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。
2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%。如果在集合中使用数据量比较大的数据,用vector有一定的优势。
3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,如果频繁的访问数据,这个时候使用vector和arraylist都可以。而如果移动一个指定位置会导致后面的元素都发生移动,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据时其它元素不移动。
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快,插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快。

arraylist和linkedlist
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

HashMap与TreeMap
1、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
2、在Map 中插入、删除和定位元素,HashMap是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。
两个map中的元素一样,但顺序不一样,导致hashCode()不一样。
同样做测试:
在HashMap中,同样的值的map,顺序不同,equals时,false;
而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。

HashTable与HashMap
1、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的。
2、HashMap允许存在一个为null的key,多个为null的value 。
3、hashtable的key和value都不允许为null。

HashMap与ArrayMap

数据量千级以内,并且需要频繁的使用Map存储数据的时候,推荐使用ArrayMap。

而数据量比较大的时候,则推荐使用HashMap。

1.查找效率

HashMap因为其根据hashcode的值直接算出index,所以其查找效率是随着数组长度增大而增加的。

ArrayMap使用的是二分法查找,所以当数组长度每增加一倍时,就需要多进行一次判断,效率下降。

所以对于Map数量比较大的情况下,推荐使用

 

2.扩容数量

HashMap初始值16个长度,每次扩容的时候,直接申请双倍的数组空间。

ArrayMap每次扩容的时候,如果size长度大于8时申请size*1.5个长度,大于4小于8时申请8个,小于4时申请4个。

这样比较ArrayMap其实是申请了更少的内存空间,但是扩容的频率会更高。因此,如果当数据量比较大的时候,还是使用HashMap更合适,因为其扩容的次数要比ArrayMap少很多。

 

3.扩容效率

HashMap每次扩容的时候时重新计算每个数组成员的位置,然后放到新的位置。

ArrayMap则是直接使用System.arraycopy。

所以效率上肯定是ArrayMap更占优势。

这里需要说明一下,网上有一种传闻说因为ArrayMap使用System.arraycopy更省内存空间,这一点我真的没有看出来。arraycopy也是把老的数组的对象一个一个的赋给新的数组。当然效率上肯定arraycopy更高,因为是直接调用的c层的代码。

 

4.内存耗费

以ArrayMap采用了一种独特的方式,能够重复的利用因为数据扩容而遗留下来的数组空间,方便下一个ArrayMap的使用。而HashMap没有这种设计。

由于ArrayMap只缓存了长度是4和8的时候,所以如果频繁的使用到Map,而且数据量都比较小的时候,ArrayMap无疑是相当的节省内存的。

 

 

 

 

Map的一般用法

1.声明一个Map:

 Map map = new HashMap();

2.向map中放值注意: map是key-value的形式存放的,如:

 map.put("sa","dd");

3.从map中取值:

 String str = map.get("sa").toString,

 结果是: str = "dd'

4.遍历一个map,从中取得key和value:

 Map m= new HashMap();

for (Map.Entry entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); }

5遍历一个map中的KeySet:

//第二种

System.out.println("通过Map.entrySet使用iterator遍历key和value:");

Iterator  it = map.entrySet().iterator();

while (it.hasNext()) {

Map.Entry entry = it.next();

System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());

}

void clear()

  从此映射中移除所有映射关系(可选操作)。

boolean containsKey(Object key)

  如果此映射包含指定键的映射关系,则返回 true。

boolean containsValue(Object value)

  如果此映射将一个或多个键映射到指定值,则返回 true。

Set> entrySet()

  返回此映射中包含的映射关系的 Set 视图。

boolean equals(Object o)

  比较指定的对象与此映射是否相等。

V get(Object key)

  返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

int hashCode()

  返回此映射的哈希码值。

boolean isEmpty()

  如果此映射未包含键-值映射关系,则返回 true。

Set keySet()

  返回此映射中包含的键的 Set 视图。

V put(K key, V value)

  将指定的值与此映射中的指定键关联(可选操作)。

void putAll(Map m)

从指定映射中将所有映射关系复制到此映射中(可选操作)。

Object remove(Object k)

如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

int size( )

返回此映射中的键-值映射关系数。

Collection values( )

返回此映射中包含的值的 Collection 视图。

 

HashMap的工作原理

HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。

当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。

因为HashMap的好处非常多,我曾经在电子商务的应用中使用HashMap作为缓存。因为金融领域非常多的运用Java,也出于性能的考虑,我们会经常用到HashMap和ConcurrentHashMap。你可以查看更多的关于HashMap的文章:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值