Collection的遍历
如图所示Collection继承了Iterable,所以遍历集合的时候。java提供了多种方法,
源码得知:
1. 迭代器
Iterator<T> iterator();
2. foreach foreach的底层就是迭代器实现的。
default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
3. Spliterators
// 返回一个内部元素为T类型的并行迭代器
default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); }
2,3方法是java8新添加的。
for foreach iterator区别
1. 条件上
- for需要知道集合或数组的大小,而且需要是有序的,不然无法遍历;
- foreach和iterator都不需要知道集合或数组的大小,他们都是得到集合内的每个元素然后进行处理;
2.多态差别
for和foreach都需要先知道集合的类型,甚至是集合内元素的类型,即需要访问内部的成员,不能实现态;
iterator是一个接口类型,他不关心集合或者数组的类型,而且他还能随时修改和删除集合的元素.不包含任何有关他所遍历的序列的类型信息,能够将遍历序列的操作与序列底层的结构分离。迭代器统一了对容器的访问方式。这也是接口的解耦的最好体现。
3. 用法差别
- for循环一般用来处理比较简单的有序的,可预知大小的集合或数组
- foreach可用于遍历任何集合或数组,而且操作简单易懂,他唯一的不好就是需要了解集合内部类型
- iterator是最强大的,对集合进行操作的时候,不需要知道元素和集合的类型,并且随时的修改和删除集合里面的元素,当对不同容器进行遍历的时候,迭代器是最好的选择。
4.效率差别
同样遍历一个集合,iterator和foreach用时不相上下。for循环用时最少。·
迭代器其他知识
迭代器是位于要遍历的两个元素之间,调用next的时候,迭代器就已经越过下一个元素
next和remove是存在依赖性的, 删除时,首先调用next.
集合框架中的接口
两个基本接口:Collection和Map
List 有序集合。允许存在重复的的对象,可以插入null元素。访问方式有两种,一种是迭代器,或者使用索引来访问,也就是所说的随机访问。可以在任意顺序下访问元素。使用迭代器就得按顺序进行访问。
常见的实现类:ArrayList、uLinkedList 和 Vector。其中ArrayList 最为流行,线程不安全,它提供了使用索引的随意访问,因为是数组列表,所以当中间删除添加元素时需要在操作位置得后面所有元素都要想数组得前端或后端移动,所以删除或添加的开销很大。
LinkedList 使用双向链表的方式存储元素,所以则对于经常需要从 List 中添加或删除元素的场合更为合适。
Vector 表示底层数组,线程安全
set:无序容器,不允许存在重复的对象,添加多个重复元素只会输出一个值,只允许插入一个null元素。添加多个空值也只会输出一个。
Set方法中最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和compareTo() 的定义进行排序的有序容器
hashCode()方法:
返回此集合的哈希代码值。集合的哈希代码定义为集合中元素的哈希代码的总和,其中空元素的哈希代码定义为零。这确保了 s1.equals(s2) 意味着任何两个集合 s1 和 s2 的 s1.hashCode()==s2.hashCode(),这是 Object.hashCode 的一般契约所要求的。返回:此集合的哈希代码值
(1412条消息) 详解为什么在foreach中不能进行remove和add操作_程熙cjp的博客-优快云博客
映射:
映射提供了两个通用的实现,HashMap和Treemap,散列映射对键进行散列,树映射对间的树的组成一个搜索树,
Hashtable 和 HashMap
链接:Hashtable 和 HashMap 的区别是:__牛客网
来源:牛客网
1. Hashtable,HashMap,Properties继承关系不同:
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
public class HashMap<K,V>extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
java.lang.Object
->java.util.Dictionary<K,V>
->java.util.Hashtable<Object,Object>
->java.util.Properties
2. 线程安全性不同:
Hashtable 中的每个方法中都加入了Synchronize,所以是线程安全的。
HashMap 中的方法在缺省情况下是非Synchronize的,线程不安全。
HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
3. key和value是否允许null值
Hashtable中,key和value都不允许出现null值
HashMap中,null可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为null,get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
4. 两个遍历方式的内部实现上不同
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
5. hash值不同
Hashtable计算hash值,直接用key对象的hashCode(),,hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。
HashMap重新计算了key的hash值。
6. 内部使用的数组初始化和扩容方式不同
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂;Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。