认真、细致。
此内容在学习过程中不断修改,仅供自己复习使用。
Iterable
|
Collection -------------- Map ------------ Iterator
| ------------------------------ | -------------------- |
List & Set & Queue — SortedMap — ListIterator
在JAVA类库中,集合类的基本接口是Collection接口。这个接口有两个基本方法:
public interface Collection<E>{
boolean add(E element);
Iterator<E> iterator(); //用于返回一个实现了Iterator接口的对象,可以遍历集合,详见五
...
}
List为有序、允许重复、线程不安全的集合
两种访问方式:迭代器、索引
动态数组:通过数组的复制实现
Java中的链表都是双向链表
Vector为线程安全的集合
Vector 类的所有方法都是同步的。可以由两个线程安全地访问一个 Vector 对象。但是 ,如果由一个线程访问Vector , 代码要在同步操作上耗费大量的时间。 这种情况还是很常见的 。而 ArrayList 方法不是同步的,因此, 建议在不需要同步使用ArrayList , 而不要使用 Vector。
Set为无序、不允许重复、线程不安全的集合。
使用了散列表相关概念。
private transient HashMap map;
private static final Object PRESENT = new Object();
为什么说Set是无序的?
无序指Set集合的添加顺序与存储顺序不一致。
Set底层采用Map集合的key值存储,通过计算hash()值来进行存储(如何存储见Map),故存储顺序与添加顺序没有半毛钱关系。
部分源码:
private transient HashMap<E,Object> map; //Set的存储空间
private static final Object PRESENT = new Object(); //作为Map的value的对象
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
Map的两个常用实现:HashMap(键值映射)、TreeMap(树映射、搜索树)
HaspMap底层实现采用了哈希表。处理散列冲突的方法为“链地址法”。
核心数组transient Node
,也称之为“位桶数组”
JDK8以后,当链表长度大于8时,链表就转为红黑树,这样提高了查找效率。
HashMap线程不安全、效率高,允许key或value为null
HashTbale线程安全、效率低、不允许key或value为null
/*HashMap类的部分代码*/
// aka 16,默认数组大小,数组大小为2的整数幂
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//核心数组,数组大小为2的整数幂
transient Node<K,V>[] table;
//Node部分代码
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}
//hash值得计算方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
hashCode()方法和equals()方法的联系:
JAVA规定,两个内容相同(equals()为true)的对象必须具有相同的hashCode。如果equals()为true而hashCode不同,那么在整个存储过程中就发生了悖论。
Iterator接口包含四个方法:
public interface Iterator<E>{
E next();
boolean hasNext();
void remove();
default void forEachRemaining(Consumer<? super E> action);
//注:jdk8以后允许在接口中定义静态方法和默认方法
/*
接口中的默认方法不要求实现,所有继承该接口的类也继承了该方法
*/
}
使用Iterator遍历集合的伪代码
Collection<String> c = ...;
Iterator<String> iter = c.iterator();
while(iter.hasNext()){
String element = iter.next();
//do something with element
}
//foreach循环
for(String str:c){
//do something with str
}
编译器简单的将foreach循环翻译为带有迭代器的循环。for each循环可以与任何实现了Iterable接口的对象一起工作,这个接口只包含一个抽象方法即iterator()
,而Collection接口继承了Iterable接口,因此,标准库中任何集合都可以使用for each循环。
还可以直接用iterator.forEachRemaining(element -> do something with element)
直接遍历
//Set和List一样
public static void testList(){
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String temp = iterator.next();
System.out.println(temp);
}
}
方式一:通过map的实体对象
public static void testMap1(){
Map<Integer, String> map = new HashMap<>();
map.put(1, "aa");
map.put(2, "dd");
map.put(3, "gg");
Set<Map.Entry<Integer, String>> set = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = set.iterator();
while(iterator.hasNext()){
Map.Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
方式二:通过map的key集合
public static void testMap2(){
Map<Integer, String> map = new HashMap<>();
map.put(1, "qq");
map.put(2, "cc");
map.put(3, "pp");
Set<Integer> set = map.keySet();
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()){
Integer temp = iterator.next();
System.out.println(temp + ":" + map.get(temp));
}
}
iterator()
,而Collection接口继承了Iterable接口,因此,标准库中任何集合都可以使用for each循环。类java.util.Collections提供了Set、List、Map进行排序、填充、查找元素的辅助方法
void sort(List)
//对List容器内的元素升序排序(自定义的类使用:Comparable接口)
void shuffle(List)
//对List容器内的元素随机排列(并非升序或降序),shuffle:调动、把…变换位置
void reverse(List)
//对List容器内的元素逆序排序(并非降序,而是对原序列反转)
void fill(List, Object)
//用一个特定的对象重写List容器
行排序、填充、查找元素的辅助方法
void sort(List)
//对List容器内的元素升序排序(自定义的类使用:Comparable接口)
void shuffle(List)
//对List容器内的元素随机排列(并非升序或降序),shuffle:调动、把…变换位置
void reverse(List)
//对List容器内的元素逆序排序(并非降序,而是对原序列反转)
void fill(List, Object)
//用一个特定的对象重写List容器
int binarySearch(List, Object)
//对于顺序的List容器,采用折半查找法查找对象