java.lang.Appendable
public interface Appendable {
Appendable append(CharSequence csq) throws IOException;
Appendable append(CharSequence csq, int start, int end) throws IOException;
Appendable append(char c) throws IOException;
}
Appendable接口表达可追加字符的能力,一般用在流相关的类上,在java.lang包下会有StringBuffer与StringBuilder实现,这两个类区别于String的不变性,可支持追加。
java.lang.CharSequence
public interface CharSequence {
int length();
char charAt(int index);
CharSequence subSequence(int start, int end);
public String toString();
public default IntStream chars() {
...
}
public default IntStream codePoints() {
...
}
}
CharSequence接口表达字符序列,包含指定位置获取字符,截取区域字符,字符长度方法。java.lang包下String,StringBuffer,StringBuilder都实现了该接口。
java.util.RandomAccess
RandomAccess接口是一个空接口,单纯就是为了区分集合底层的实现方式的,列表的底层实现方式可以简单的分为两种,数组实现和链表实现。
数组实现的列表将会对使用index访问的操作效率较高;而链表实现的列表则在使用index访问元素效率不高,相反在特定位置上插入,删除元素效率很高。因此会导致在遍历的时候,可以采用的方式也会有两种:一种是使用过index下标访问,另一种是使用迭代器访问。RandomAccess就是为了标识出那些底层是使用数组实现的类,在不同实现下使用不同的实现方法。如下方法,选自Collections源码:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
java.util.Interable
Interable的存在是为了让集合对象可以用for循环进行迭代遍历所含元素。其源码如下:
public interface Iterable <T>{
//(1)返回迭代器
Iterator<T> iterator();
// (2) 遍历所有元素
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
java中的集合类型都会实现Collection接口,而collection接口会继承迭代器接口,意味着所有集合都可以使用迭代器进行遍历操作。
public interface Collection<E> extends Iterable<E> {
}
这里写个测试case来描述迭代器是如何使用的:
@Test
public void test001(){
Collection<String> c = Arrays.asList("1","2","3");
Iterator<String> iterator = c.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
迭代器模式在语法糖层面也有关联,例如:
@Test
public void test002(){
Collection<String> c = Arrays.asList("1","2","3");
for(String s : c){
System.out.println(s);
}
}
获得此方法的字节码:
0 iconst_3
1 anewarray #2 <java/lang/String>
4 dup
5 iconst_0
6 ldc #3 <1>
8 aastore
9 dup
10 iconst_1
11 ldc #4 <2>
13 aastore
14 dup
15 iconst_2
16 ldc #5 <3>
18 aastore
19 invokestatic #6 <java/util/Arrays.asList : ([Ljava/lang/Object;)Ljava/util/List;>
22 astore_1
23 aload_1
24 invokeinterface #7 <java/util/Collection.iterator : ()Ljava/util/Iterator;> count 1
29 astore_2
30 aload_2
31 invokeinterface #8 <java/util/Iterator.hasNext : ()Z> count 1
36 ifeq 59 (+23)
39 aload_2
40 invokeinterface #10 <java/util/Iterator.next : ()Ljava/lang/Object;> count 1
45 checkcast #2 <java/lang/String>
48 astore_3
49 getstatic #9 <java/lang/System.out : Ljava/io/PrintStream;>
52 aload_3
53 invokevirtual #11 <java/io/PrintStream.println : (Ljava/lang/String;)V>
56 goto 30 (-26)
59 return
可以看到24-40行字节码内实际上是针对其迭代器进行执行。
java.util.Collection
Collection接口可以说为集合框架定下一个基调,所有的集合都应该有这个类定义的行为
public interface Collection<E> extends Iterable<E> {
// 集合大小及基础判定
int size();
boolean isEmpty();
boolean contains(Object o);
// 集合遍历能力
Iterator<E> iterator();
//转换操作
Object[] toArray();
<T> T[] toArray(T[] a);
//操作集合内元素相关,并集 交集实现
boolean add(E e);
boolean addAll(Collection<? extends E> c);
boolean remove(Object o);
boolean removeAll(Collection<?> c);
boolean containsAll(Collection<?> c);
boolean retainAll(Collection<?> c);
// 清除集合内元素
void clear();
// 1.8新加默认实现方法,基于迭代器遍历实现
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
// 以下是流式编程的默认方法
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
boolean equals(Object o);
int hashCode();
}
可以看到这个接口内定义的是集合相关操作,这里进行分组描述:
- 描述当前集合的状态
- 当前集合的大小
- 当前集合是否为空
- 当前集合是否包含某个元素(集合领域的 ‘属于’ 操作)
- 当前集合是否包含另一个集合(集合领域的 ‘是否为子集’ 操作)
- 集合内元素操作:
- 增加 一个/多个 元素
- 删除 一个/多个 元素
- 在某一条件下进行删除元素
- 针对当前集合的操作
- 遍历能力:使用迭代器遍历
- 对当前集合进行清理
- 转换当前集合内元素为数组
- 针对多个集合间的操作
- 两个集合进行交集
- 两个集合进行并集(数学意义上需要进行去重,这里的集合概念可以进行不去重)
这里将一些常用的AbstractCollection的源码拿出来看看是怎么实现的:
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
public boolean remove(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext())