JAVA总结--集合
1、集合树状图
Collection:最基本的集合接口
----List:有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问
----ArrayList:异步
----LinkedList:实现了List和Queue的双接口
----Vector:同步
----Stack:后进先出,同步
----Queue:先入先出(FIFO)数据结构的集合
----LinkedList:实现了List和Queue的双接口
----Set:无序集合,集合中的元素不可以重复,最多有一个null元素
----EnumSet:枚举类型专用,单一枚举类型,无null元素,异步
----SortedSet:继承了Set接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序
----TreeSet:实现了SortedSet接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeSet的自然排序方式)。(Tips:Set内部源码仍以Map为基础,是value为空对象的Key集合)
----HashSet:异步,最多有一个null元素
----LinkedHashSet:继承HashSet,调用了 LinkedHashMap中记录插入元素顺序的recordAccess()方法。
MAP:保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value
----HashMap:异步,允许null,即null value和null key
----WeakHashMap:对key实行“弱引用”,如果一个key不再被外部所引用,该key可以被GC回收
----Hashtable:同步,不允许null
----SortedMap:继承了Map接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序
----TreeMap:实现了SortedMap接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeMap的自然排序方式)
2、集合统计信息
对于Set、List和Map三种集合,最常用的实现类分别是HashSet、ArrayList和HashMap三个实现类;
Vector、HashTable、Properties和Stack是同步类,所以它们是线程安全的,可以在多线程环境下使用;
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问;
3、集合遍历
Iterator(迭代器) :hasNext() next() remove()
当前遍历的集合元素被更改的时候,会抛出ConcurrentModificationException,避免报错CopyOnWriteArrayList;(Enumeration不会,不安全)
for(for循环):
一:for(Iterator iterator = list.iterator();iterator.hasNext();)
二:Iterator iterator = list.iterator(); while(iterator.hasNext()){
三:for (Object object : list) {(从JDK1.5开始出现的语法,相当于 while(iterator.hasNext(),所以这里的for循环内部还是迭代器方式遍历)
四: for (int i = 0 ;i<list.size();i++) {
4、原理
一、Hashtable、HashMap、HashSet的实现原理:
底层数据结构是哈希表;
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:自动生成hashCode()和equals()即可;
二、线程安全:Hashtable和ConcurrentHashMap
Hashtable:synchronized是针对整张Hash表的,即每次锁住整张表让线程独占;
ConcurrentHashMap:锁分离,使用了多个锁来控制对hash表的不同部分(段Segment);但size()和containsValue()等方法依然是跨段对整个表进行加锁(按顺序锁定所有段);ConcurrentHashMap的迭代器为弱一致性,即在遍历并遇到修改时会复制数据进行遍历,遍历结束再将迭代器指针指向新数据。
各种集合的原理详解---jdk源码
Arraylist LinkList HashMap HashSet
1.ArrayList
private transient Object[] elementData;
private int size;
public ArrayList(int paramInt)
{
if (paramInt < 0)
throw new IllegalArgumentException("Illegal Capacity: " + paramInt);
this.elementData = new Object[paramInt];
} public ArrayList()
{
this(10);
}
ArrayList构造方法,支持预定长度,使用类中的全局变量Object类型的数组,进行数据的保存。
2.LinkList
private transient Entry<E> header;
private transient int size;
public LinkedList()
{
this.header = new Entry(null, null, null);
this.size = 0; this.header.next = (this.header.previous = this.header);
} public LinkedList(Collection<? extends E> paramCollection)
{
addAll(paramCollection);
}
LinkList 构造方法,支持预设值一个集合,方法addAll为for循环创建并增加集合数据。
private static class Entry<E>
{
E element;
Entry<E> next;
Entry<E> previous; Entry(E paramE, Entry<E> paramEntry1, Entry<E> paramEntry2)
{
this.element = paramE;
this.next = paramEntry1;
this.previous = paramEntry2;
}
}
LinkList 中的Entry 为静态内部私有类,包括前后指针和数据。
3.HashMap 存储/读取数据原理:
//定义
//private transient Set<Map.Entry<K, V>> entrySet; public HashMap(int paramInt)
{
this(paramInt, 0.75F);
} public HashMap()
{
this.entrySet = null; this.loadFactor = 0.75F;
this.threshold = 12;
this.table = new Entry[16];
init();
} public HashMap(Map<? extends K, ? extends V> paramMap)
{
this(Math.max((int)(paramMap.size() / 0.75F) + 1, 16), 0.75F); putAllForCreate(paramMap);
}
HashMap在无参数下,初始化entry为16(2的指数),仅保存12个元素;以16为基础翻倍扩容,存储数据以12为基础翻倍增加;
public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
private static final int MINIMUM_CAPACITY = 4;
...
transient HashMapEntry<K, V>[] table;
...
private static final Entry[] EMPTY_TABLE
= new HashMapEntry[MINIMUM_CAPACITY >>> 1];
...
@Override public V put(K key, V value) {
if (key == null) {
return putValueForNullKey(value);
} int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
preModify(e);
V oldValue = e.value;
e.value = value;
return oldValue;
}
} // No entry for (non-null) key is present; create one
modCount++;
if (size++ > threshold) {
tab = doubleCapacity();
index = hash & (tab.length - 1);
}
addNewEntry(key, value, hash, index);
return null;
}
...
public V get(Object key) {
if (key == null) {
HashMapEntry<K, V> e = entryForNullKey;
return e == null ? null : e.value;
} int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
e != null; e = e.next) {
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
return e.value;
}
}
return null;
}
...
}
分析下put方法的实现:
- if (key == null) {
return putValueForNullKey(value);
}
首先判断是否为null,如果为null则特殊处理;
- 2、int hash = Collections.secondaryHash(key);
获取Key的二级hash值,其中Collections.secondaryHash方法的实现就是把Key的hashcode值做一定改变;
- int index = hash & (tab.length - 1);
通过刚才计算的hash值来获取该key应该存放在数组的下标位置,也就是获取该数据应该存储在table数组的哪个位置;
- for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
preModify(e);
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
如果已经有该key存在了,则覆盖这个key的值value。
注意这里的判断:因为只有两个对象的hashcode值相等并且两个对象用equals判断返回true时,才去覆盖原有的值;
- if (size++ > threshold) {
tab = doubleCapacity();
index = hash & (tab.length - 1);
}
addNewEntry(key, value, hash, index);
如果该key不存在,或者发生碰撞的对象不是一个对象时,则需要把它存储下来。首先如果存储数量已经大于数组大小,则把数组双倍扩大。然后再把键值对保存到数组中。
注意这里保存的时候,如果数组存储位置原本就存在键值对,那么则把新的键值对对象保存到旧的键值对 对象next变量中,构成链表。
- hashMap是table和entry的组合,他的扩容机制,保证table与entry比例均衡,对table的查询与entry的修改的优点进行均衡采用。
4.HashSet
private transient HashMap<E, Object> map;
private static final Object PRESENT = new Object();
public HashSet()
{
this.map = new HashMap();
}
public boolean add(E paramE)
{
return (this.map.put(paramE, PRESENT) == null);
}
由源码可见,HashSet用的就是HashMap实现的,其类中定义一个final状态的Object对象,作为每个数据元素的value,HashSet仅仅使用HashMap的key进行数据的保存,其remove等方法均调用HashMap的方法实现。
JAVA总结--集合的更多相关文章
- 【Java】集合_学习笔记
一.集合 1.集合类也称容器类,主要负责保存.盛装其他数据. 2.集合可以保存数量不确定的数据,保存具有映射关系的数据(也称关联数组). 3.Java5后提供一些多线程安全的集合类,放在java.ut ...
- java的集合框架最全详解
java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...
- 谈谈Java的集合组件
让我们一起谈谈Java的集合组件 我们在使用Java的时候,都会遇到并使用到Java的集合.在这里通过自己的理解和网上的资源对Java的集合方面的使用做一个简单的讲解和总结. Java主要分为3个集合 ...
- java.util 集合框架集合
java的集合框架为程序提供了一种处理对象组的标准方式.设计了一系列标准泛型接口: ⑴Collection ()接口,扩展了Iterable接口,位于集合层次结构的顶部,因此所有的集合都实现Colle ...
- Java基础——集合框架
Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...
- Java学习-集合(转)
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...
- java的集合框架之一
java是一套很成熟的东西,很多商用的东西都喜欢用它,用的人多,稳定.不过一般也不怎么说起它,因为太常见了,私下里说,写java应用层得就像农民工,每一处都是搭积木,根据设计师的东西如何优雅地搭好积木 ...
- 浅谈Java的集合框架
浅谈Java的集合框架 一. 初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...
- Java之集合初探(一)
一.集合概述.区别 集合是一种容器,数组也是一种容器 在Java编程中,装各种各样的对象(引用类型)的叫做容器. 为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的 ...
- Java面向对象 集合(下)
Java面向对象 集合(下) 知识概要: (1)Map集合的体系结构 (2)Map集合的方法 (3)HashMap TreeMap (4)集合框架中的常用工具类 ( ...
随机推荐
- memcpy函数的用法以及实现一个memcpy函数
memcpy的用法 在项目中经常用到memcpy来实现内存的拷贝工作,如下代码片段 memcpy( pData, m_pSaveData_C, iSize * sizeof( unsigned sho ...
- JS实现网页飘窗
1.在html中设置一个飘窗的div,div中可以添加图片,添加文字通过css展现在飘窗中: <!--飘窗--> <div id="roll"> <i ...
- 过滤函数filter
>>> def validate(usernames): if (len(usernames) > 4) and (len(usernames) < 12): retur ...
- 【leetcode】837. New 21 Game
题目如下: 解题思路:这个题目有点像爬楼梯问题,只不过楼梯问题要求的计算多少种爬的方式,但是本题是计算概率.因为点数超过或者等于K后就不允许再增加新的点数了,因此我们可以确定最终Alice拥有的点数的 ...
- 接口返回buffer的16进制数据如何转换
我们请求接口数据经常会看到buffer数据,这是我们可以使用data.toString()就可以啦~
- java.util.Properties的使用及读取资源文件
1.工具类Utils package com.oy.utils; import java.io.BufferedInputStream; import java.io.Closeable; impor ...
- 倍增O(1)求区间&值与|值
;i<=n;++i) f[i][]=a[i],g[i][]=a[i]; ;(<<j)<=n;++j) ;(i+(<<j)-)<=n;i++) { f[i][j ...
- 关联规则挖掘--Eclat算法
- 一文读懂跨平台框架 Flutter 的搭建与运行
作者:个推iOS开发工程师 伊泽瑞尔 Flutter是Google推出的跨平台的解决方案,用以帮助开发者在 Android 和 iOS 两个平台开发高质量原生应用的全新移动 UI 框架. 之前我们为大 ...
- ionic使用自定义icon
参考文档:https://www.jianshu.com/p/5346fee9fd80 angular+ionic 自定义图标 注意: 这里不用name 用class类名显示出来 最后出来图标是个小 ...