您的位置:首页 > 编程语言 > Java开发

关于ArraysList,LinkedList,HashSet,LinkedHashSet,TreeSet的总结

2017-12-27 22:40 429 查看
关于ArraysList,LinkedList,HashSet,LinkedHashSet,TreeSet的总结
ArraysList:底层是数组,有序结构,按照进栈先后分配索引,查找方便,属于先进后出,如果从后面取元素,效率快

在指定位置添加元素时,(System.arraycopy(elementData, index, elementData, index + 1, size - index);elementData[index] = element),采用数组复制方式,将指定索引到最后的元素向后移动一位,然后在指定位置添加元素,涉及数组复制,效率较低。(测试:向列表插入10000个元素用时9ms)

进行查找元素时,1.查找指定索引的值,(return (E) elementData[index]),直接按照给定索引取值。(测试顺序查找10000个元素用时1ms)

2.查找指定元素的值,遍历数组查找。测试顺序查找10000个元素用时142ms

进行元素删除时,采用数组复制方式,将删除元素后面的元素向前复制一位,涉及数组复制,效率较低。(测试:向列表删除10000个元素用时10ms)
LinkedList:底层是链表,同样是有序结构,使用不连续内存地址进行存储,链式存储,每个元素对应两个(final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev;)前后索引,查找较慢。

在指定位置添加元素时,(if (index == size) linkLast(element); else linkBefore(element, node(index));采用元素节点前后链接方式,效率快.(测试:向列表插入10000个元素用时3ms)

进行元素查找时,1.查找指定索引的值( if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++)
x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; }),采用前后查找方式,逐一对比。(测试顺序查找10000个元素用时40ms)

2.查找指定元素的值,遍历链表查找。测试顺序查找10000个元素用时208ms

进行元素删除时,采用前一个元素和后一个元素直接相连,实现删除,效率快。(测试:向列表删除10000个元素用时2ms)
小结:List的存储可以重复的元素,元素有序,按照加入顺序给出索引。具有sort函数进行排序,逆序排列需要制定比较器。元素反转需要调用Collections的reverse方法。两种表进行指定元素查找contains(e)使用的方法一致,
HashSet,LinkedHashSet底层是Hash表,通过HashCode和equals进行判断,如果HashCode相同,equals也相同,认为是同一个元素,不进行存储。如果HashCode相同,equals不相同,使用链式存储,在同一个地址位置存储多个元素,如果Hashcode不相同,则直接存储。遍历元素使用foreach或者iterator
输入元素:{2,322,1,33,233,225,33,6,733,8,5};
HashSet:相对无序存储(相对无序是指不是按照加入顺序,或者自然排序,其顺序是按照hashcode的地址映射顺序存储),按照hashcode映射地址存储,元素不能重复,无法进行排序。无法获取指定元素。需要进行操作,可以将其转换为数组进行操作。存储结果:[1, 33,
225, 2, 322, 5, 6, 8, 233, 733]

添加元素:add(E e),添加元素,调用map.put(e, new Object),调用return putVal(hash(key), key, value, false, true);将元素值转换成hash键值对,然后进行比较hash(key)和value的值,进行插入,使用的HashMap,putVal(int
hash, K key, V value, boolean onlyIfAbsent, boolean evict)。对HashSet插入9,插入前后分别为:[1, 33, 225, 2, 322, 5, 6, 8, 233, 733],[1, 33, 225, 2, 322, 5, 6, 8, 233, 9, 733]。速度测试插入10000,用时4ms

查找元素:通过HashMap的contains(Object o),查找键值对getNode(hash(key), key),遍历查找do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null);,查找指定元素的值。测试顺序查找10000个元素用时3ms

删除元素:使用HashMap的remove(Object key),e = removeNode(hash(key), key, null, false, true)),通过removeNode(int hash, Object key, Object value, boolean matchValue,
boolean movable)判断键值对,对元素进行删除。速度测试删除10000,用时4ms
LinkedHashSet:是对HashSet的包装,通过链式存储,使得元素具有一定顺序,按照进入序列的顺序的存储。存储结果:[2, 322, 1, 33, 233, 225, 6, 733, 8, 5]

添加元素:操作方式与HashSet方式方法一致,在最后插入时通过判断afterNodeInsertion(evict),来判断是否是LinkedHashSet,是的话进行链表式存储。对LinkedHashSet插入9,插入前后分别为:[2, 322, 1, 33, 233, 225, 6, 733, 8, 5],[2, 322, 1, 33, 233, 225, 6, 733, 8, 5, 9]。速度测试插入100000,用时4ms

查找元素:查找指定元素的值。操作方式与HashSet方式方法完全一致,测试顺序查找10000个元素用时3ms

删除元素
4000
:操作方式与HashSet方式方法一致,在最后删除时通过判断afterNodeRemoval(node);,来判断是否是LinkedHashSet,是的话进行链表式删除。速度测试删除10000,用时3ms
TreeSet:使用二叉树对元素进行存储,存储结果有序。存储结果:[1, 2, 5, 6, 8, 33, 225, 233, 322, 733],可以在定义时指定比较器TreeSet<Integer> c = new TreeSet<>((s1,s2) -> s2 -
s1);,输出结果为:[733, 322, 233, 225, 33, 8, 6, 5, 2, 1]

添加元素:使用Map的put(K key, V value)进行插入。速度测试插入10000,用时13ms

查找元素:使用Map的containsKey(Object key)查找指定元素的值。测试顺序查找10000个元素用时4ms

删除元素:使用Map的 remove(Object key)进行删除。速度测试删除10000,用时9ms
小结:HashSet和LinkedHashSet的方法基本一致,使用HashMap的相关方法进行操作,无序不重复,LinkedHashSet仅仅添加了记录存储位置前后的地址,使得集合有序。TreeSet使用Map的相关方法,同时对插入元素进行排序。在性能方面有所影响。
关于如何选择使用,需要根据不同的背景条件进行选择

PS:初学者JAVA,有总结不足之处欢迎指教。代码参考JDK8源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐