java 集合与数组

1.集合和数组的区别:

集合:大小可以动态扩展,可以存储不同的数据类型

数组:大小固定,只能存储相同的数据类型,是java语言内置的数据类型,执行效率和类型检查都是最快的

数组转成集合:

Arrays.asList(数组);

集合转成数组:集合.toArray();

2.集合

集合的最顶层是两个接口:Collection    和     Map

Collection下面的子接口:List(有序、可重复)、Set(无序、唯一)、Queue

Map下面的子接口不怎么用到,就不写了,主要研究实现类:HashMap、HashTable、TreeMap、CurrentHashMap

List的实现类有:ArrayList、LinkedList、Vector

Set的实现类有:TreeSet、HashSet、LinkedHashSet

2.1 ArrayList:

是实现List的动态数组,每个ArrayList实例都有一个容量,用来存储列表元素的数组的大小。默认容量为10。

随着容量的不断增加,效率会变低,因为每次添加元素的同时,ArrayList都会检查是否需要进行扩容操作,如果进行扩容操作会导致数据向新数组的重新拷贝,循环这样一直操作不利于代码性能。解决方法:通过预先设置容量list.ensureCapacity(N);

ArrayList是线程不安全的,那为什么是不安全的呢?源码来分析:

首先ArrayList用一个Object的数组用来保存所有的元素,以及一个size变量用来保存当前数组保存了多少元素

transient Object[] elementData;

private int size;

线程不安全的地方在于add()的时候,add内部源码如下:

public boolean add(){
    /**
     * 添加一个元素时,做了如下两步操作
     * 1.判断列表的capacity容量是否足够,是否需要扩容
     * 2.真正将元素放在列表的元素数组里面
     */
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

add实际做了两个步骤:

1.判断elementData数组容量是否满足需求

2.在elementData对应位置上设置值

发生线程不安全的情况主要在elementData[size++]  = e这行,

此行可以解析成elementData[size] = e; size = size + 1;

多线程操作的话就会出现同一个索引位置值覆盖的情况。

怎么解决ArrayList的不安全?

使用CopyOnWriteArrayList 代替线程不安全的ArrayList()

2.2 LinkedList

是通过双向链表实现的。双向链表就是通过Node类来体现的。增加删除快,查询慢

2.3 HashMap

底层数据结构是  数组+链表或者红黑树,当链表长度超过8的时候转成红黑树

采用这种数据结构的原因:数组查询效率高,添加删除效率低;链表查询效率低,添加删除效率高

存储过程:

HashMap<String,String> map = new HashMap<String,String>();
map.put("刘德华","张惠妹");
map.put("张学友","大S");

计算出键“刘德华”的hashcode,该值用来定位要将这个元素存放到数组中的什么位置,数组默认长度为16

刘德华的hashcode为20977295 数组长度为 16则要存储在数组索引为 20977295%16=1的地方

可以分两种情况:

1. 数组索引为1的地方是空的,这种情况很简单,直接将元素放进去就好了。

2. 已经有元素占据了索引为1的位置,这种情况下我们需要判断一下该位置的元素和当前元素是否相等,使用equals来比较。

如果两者相等则直接覆盖如果不等则在原元素下面使用链表的结构存储该元素

HashMap中有两个重要的参数:初始容量大小和加载因子,初始容量大小是创建时给数组分配的容量大小,默认值为16,用数组容量大小乘以加载因子得到一个值,一旦数组中存储的元素个数超过该值就会调用rehash方法将数组容量增加到原来的两倍,专业术语叫做扩容.

在做扩容的时候会生成一个新的数组,原来的所有数据需要重新计算哈希码值重新分配到新的数组,所以扩容的操作非常消耗性能.

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值