距今为止,我们了解的都是普通类的定义,那就是直接在IDEA中直接新建一个class。
新建完成后,你就会拥有一个class文件的定义,这种操作太简单了,时间长了就会枯燥,我们年轻人多需要更新潮和骚气的写法,好吧,既然你提到了那就使用内部类吧,这是一种有用而且骚气的定义类的方式,内部类的定义非常简单︰可以将一个类的定义放在另一个类的内部,这就是内部类。
内部类是一种非常有用的特性,定义在类内部的类,持有外部类的引用,但却对其他外部类不可见,看起来就像是一种隐藏代码的机制,就和弗兰奇将军似的,弗兰奇可以和弗兰奇将军进行通讯,但是外面的敌人却无法直接攻击到弗兰奇本体。
定义内部类非常简单,就是直接将一个类定义在外围类的里面,如下代码所示
public class OuterClass {
private String name;
private int age;
class InnerClass{
public InnerClass(){
name = "cxuan";
age = 25;
}
}
}
在这段代码中,InnerClass 就是OuterClass 的一个内部类。也就是说,每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。这也是隐藏了内部实现细节。内部类拥有外部类的访问权
内部类不仅仅能够定义在类的内部,还可以定义在方法和作用域内部,这种被称为局部内部类,除此之外,还有匿名内部类、内部类可以实现Java 中的 多重继承。下面是定义内部类的方式
由于每个类都会产生一个 .class 文件,其中包含了如何创建该类型的对象的全部信息,那么,如何表示内部类的信息呢?可以使用 $ 来表示,比如OuterClass$InnerClass.class
集合在我们的日常开发中所使用的次数简直太多了,你已经把它们都用的熟透了,但是作为一名合格的程序员,你不仅要了解它的基本用法,你还要了解它的源码;存在即合理,你还要了解它是如何设计和实现的,你还要了解它的衍生过程。
这篇博客就来详细介绍一下Collection这个庞大集合框架的家族体系和成员,让你了解它的设计与实现。
是时候祭出这张神图了
首先来介绍的就是列表爷爷辈儿的接口 - Iterator
实现此接口允许对象成为for-each 循环的目标,也就是增强for 循环,它是Java中的一种语法糖
List<Object> list = new ArrayList();
for (Object obj: list){}
除了实现此接口的对象外,数组也可以用for-each 循环遍历,如下:
Object[] list = new Object[10];
for (Object obj: list){}
其他遍历方式
jdk 1.8之前Iterator只有iterator 一个方法,就是
Iterator<T> iterator();
实现次接口的方法能够创建一个轻量级的迭代器,用于安全的遍历元素,移除元素,添加元素。这里面涉及到一个fail-fast机制
总之一点就是能创建迭代器进行元素的添加和删除的话,就尽量使用迭代器进行添加和删除
也可以使用迭代器的方式进行遍历
for(Iterator it = coll.iterator(); it.hasNext(); ){
System. out.println(it.next());
}
Collection是一个顶层接口,它主要用来定义集合的约定
List 接口也是一个顶层接口,它继承了Collection接口,同时也是ArrayList、LinkedList等集合元素的父类
Set 接口位于与List 接口同级的层次上,它同时也继承了Collection接口。Set 接口提供了额外的规定。它对add、equals、hashCode方法提供了额外的标准
Queue是和List、Set 接口并列的Collection 的三大接口之一。Queue 的设计用来在处理之前保持元素的访问次序。除了Collection基础的操作之外,队列提供了额外的插入,读取,检查操作
SortedSet 接口直接继承于Set 接口,使用Comparable对元素进行自然排序或者使用Comparator在创建时对元素提供定制的排序规则。set的迭代器将按升序元素顺序遍历集合
Map是一个支持 key-value存储的对象,Map 不能包含重复的key,每个键最多映射一个值。这个接口代替了Dictionary类,Dictionary是一个抽象类而不是接口
ArrayList是实现了List 接口的可扩容数组(动态数组),它的内部是基于数组实现的。它的具体定义如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>,
RandomAccess,Cloneable,java.io.Serializable {...}
List list = Collections.synchronizedList(new ArrayList(...))
Vector同ArrayList 一样,都是基于数组实现的,只不过Vector是一个线程安全的容器,它对内部的每个方法都简单粗暴的上锁,避免多线程引起的安全性问题,但是通常这种同步方式需要的开销比较大,因此,访问元素的效率要远远低于ArrayList。
还有一点在于扩容上,ArrayList扩容后的数组长度会增加50%,而Vector 的扩容长度后数组会增加一倍。
LinkedList 是一个双向链表,允许存储任何元素(包括null )。它的主要特性如下:
List list = Collections.synchronizedList(new LinkedList( ...))
堆栈是我们常说的 后入先出(吃了吐) 的容器。它继承了Vector类,提供了通常用的push和 pop 操作,以及在栈顶的 peek方法,测试 stack 是否为空的empty方法,和一个寻找与栈顶距离的search方法
第一次创建栈,不包含任何元素。一个更完善,可靠性更强的LIFO栈操作由Deque接口和他的实现提供,应该优先使用这个类
Deque<Integer> stack = new ArrayDeque<Integer>()
HashSet是Set 接口的实现类,由哈希表支持(实际上HashSet 是 HashMap的一个实例)。它不能保证集合的迭代顺序。这个类允许null元素。
TreeSet是一个基于TreeMap的 NavigableSet 实现。这些元素使用他们的自然排序或者在创建时提供的Comparator进行排序,具体取决于使用的构造函数。
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...))
LinkedHashSet继承于Set,先来看一下LinkedHashSet的继承体系:
LinkedHashSet是 Set接口的 Hash 表和LinkedList的实现。这个实现不同于HashSet 的是它维护着一个贯穿所有条目的双向链表。此链表定义了元素插入集合的顺序。注意:如果元素重新插入,则插入顺序不会受到影响。
Collections.synchronizedSet
PriorityQueue是AbstractQueue 的实现类,优先级队列的元素根据自然排序或者通过在构造函数时期提供Comparator来排序,具体根据构造器判断。PriorityQueue 不允许 null元素
HashMap是一个利用哈希表原理来存储元素的集合,并且允许空的 key-value键值对。HashMap是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而 Hashtable是线程安全的容器。
HashMap也支持 fail-fast 机制。HashMap 的实例有两个参数影响其性能︰初始容量和加载因子。可以使用Collections.synchronizedMap(new HashMap(…))来构造一个线程安全的HashMap。
一个基于NavigableMap 实现的红黑树。这个map根据key自然排序存储,或者通过Comparator进行定制排序。
LinkedHashMap 是Map接口的哈希表和链表的实现。这个实现与HashMap 不同之处在于它维护了一个贯穿其所有条目的双向链表。这个链表定义了遍历顺序,通常是插入map 中的顺序。
Hashtable类实现了一个哈希表,能够将键映射到值。任何非空对象都可以用作键或值。
ldentityHashMap是比较小众的Map 实现了
WeakHashMap类基于哈希表的Map基础实现,带有弱键。WeakHashMap中的entry当不再使用时还会自动移除。更准确的说,给定key的映射的存在将不会阻止 key被垃圾收集器丢弃
Collections 不属于Java框架继承树上的内容,它属于单独的分支,Collections是一个包装类,它的作用就是为集合框架提供某些功能实现,此类只包括静态方法操作或者返回collections。
同步包装
同步包装器将自动同步(线程安全性)添加到任意集合。六个核心集合接口(Collection,Set,List,Map,SortedSet和 SortedMap)中的每一个都有一个静态工厂方法。
public static Collection synchronizedCollection(Collection c);
public static Set synchronizedSet(Set s);
public static List synchronizedList(List list);
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
public static SortedSet synchronizedSortedSet(SortedSet s);
public static <K,V>SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m);
不可修改的包装
不可修改的包装器通过拦截修改集合的操作并抛出UnsupportedOperationException ,主要用在下面两个情景:
这些方法是:
public static Collection unmodifiableCollection(Collection<? extends T> c);
public static Set unmodifiableSet(Set<? extends T> s);
public static List unmodifiableList(List<? extends T> list);
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m);
public static SortedSet unmodifiableSortedSet(SortedSet<? extends T> s);
public static <K,V>SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extendsV> m);
线程安全的Collections
Java1.5并发包(java.util.concurrent)提供了线程安全的collections 允许遍历的时候进行修改,通过设计iterator为 fail-fast并抛出ConcurrentModification
Exception。一些实现类是CopyOnWriteArrayList ,ConcurrentHashMap , CopyOnWriteArraySet
Collections 算法
此类包含用于集合框架算法的方法,例如二进制搜索,排序,重排,反向等