java集合框架
Java集合工具包的位置是java.util.*
Collection接口:
是高度抽象出来的集合,包含了集合的基本操作和属性
Collection包含了List和Set两大分支
-
List: List是一个有序的队列,每一个元素都有它的索引,第一个元素的索引值是0;List的实现类有:
① LinkedList
② ArrayList
③ Vector
④ Stack -
Set:Set是一个不允许有重复元素的集合;Set的实现类有:
① HashSet:依赖于HashMap,是通过HashMap实现的
② TreeSet:依赖于TreeMap,是通过TreeMap实现的
Iterable接口
Collection 继承了 Iterable< E > 接口,Iterable 接口内只有一个 iterator 方法,返回一个 Iterator 迭代器:
public interface Iterable<T> {
/**
* Returns an {@link Iterator} for the elements in this object.
*
* @return An {@code Iterator} instance.
*/
Iterator<T> iterator();
}
Iterator接口
它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现iterator()函数,返回一个Iterator对象。
通过Iterable定义的iterator()接口可以拿到iterator
List接口
一个 List 是一个元素有序的、可以重复、可以为 null 的集合(有时候我们也叫它“序列”)。
Java 集合框架中最常使用的几种 List 实现类是 ArrayList,LinkedList 和 Vector。在各种 List 中,最好的做法是以 ArrayList 作为默认选择。 当插入、删除频繁时,使用 LinkedList,Vector 总是比 ArrayList 慢,所以要尽量避免使用它
在List中除了继承Collection中的一些方法,还提供了以下操作
① 位置相关:List 和 数组一样,都是从 0 开始,我们可以根据元素在 list 中的位置进行操作,比如说
get, set, add, addAll, remove;
② 搜索:从 list 中查找某个对象的位置,比如 indexOf, lastIndexOf;
③ 迭代:使用 Iterator 的拓展版迭代器 ListIterator 进行迭代操作;
④ 范围性操作:使用 subList 方法对 list 进行任意范围的操作
**其中在List接口中定以了 ListIterator listIterator()方法用来返回一个listIterator(),listIterator()更强大它可以双向遍历,同时还允许进行add,set,remove等操作 **
AbstractCollection接口
AbstractCollection是对Collection接口的直接实现类(是一个抽象类),Collection下的大多数子类都要继承AbstractCollection,他实现了一些方法,也定义了一些抽象方法留给子类实现
抽象方法
public abstract Iterator<E> iterator();
public abstract int size();
注意:
在AbstractCollection中不支持添加单个元素,所以直接调用add(E)方法会报错,如果子类是可添加的数据结构,需要自己实现这些方法
public boolean add(E object) {
throw new UnsupportedOperationException();
}
这样设计主要是因为如果你想修改一个不可变的集合时,抛出 UnsupportedOperationException 是标准的行为,比如 当你用 Collections.unmodifiableXXX() 方法对某个集合进行处理后,再调用这个集合的 修改方法(add,remove,set…),都会报这个错;
AbstractList
AbstractList 继承自 AbstractCollection 抽象类,实现了 List 接口 ,是 ArrayList 和 AbstractSequentiaList 的父类。它实现了 List 的一些位置相关操作,是第一个实现随机访问方法的集合类,但不支持添加和替换。还是默认不支持add(),set(),remove()操作
在AbstractList 中实现了ListIterator和Iterator
1. Iterator的实现
private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;//为的是remove操作
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
需要注意的地方是:
① 如果没有执行过next(), 直接remove()会抛异常。因为没对象让你移除。然后,每次移除完成之后,lastRet = -1 , 又回到了,next()之前的状态。也就意味着。每次 remove()之前都必须调用一次next(),否则报错。
② 因为迭代器的remove方法会同步expectedModCount和modCount所以不会fast-fail
2. ListIterator的实现
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
在ListIterator和Iterator中的next() 和remove() 等方法都会调用AbstractList的get()和remove()方法,而这些方法又会在子类中进行重写实现,也就是说,子类调用迭代器后迭代器里实际调用的是自己的get()和remove()方法
Map接口
Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。
AbstractMap是个抽象类,实现了Map接口的大部分API,① HashMap,② TreeMap,③ WeakHashMap都是继承于AbstractMap
总结
List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口
List接口的实现类有ArrayList,Vector,LinkedList
Set接口的实现类有HashSet,LinkedHashSet,TreeSet
Map接口的实现类有Hashtable,LinkedHashMap,HashMap,TreeMap
自己实现
MyIterator接口
package interfacePag;
public interface MyIterator<T> {
boolean hasNext();
T next();
void remove();
}
MyIterable接口
所有的集合操作都实现了Collection接口,也就是在Collection接口中定义了常规都需要的方法,而且要使用泛型
而Collection接口继承于Iterable接口,所以应该先去定义Iterable接口,实现这个接口实现对象的增强,变成可迭代的
package interfacePag;
import java.util.Iterator;
public interface MyIterable<T>{
/**
*
* @return 返回该类型的迭代器
*/
MyIterator<T> iterator();
//下面的看不懂了
/*default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}*/
}
MyCollection接口
这个接口是为了集合操作的最大通用性,不会直接提供这个接口的实现,而是会通过实现其子接口(List,set)加以使用
规定:
-
所以的集合都应该实现两个构造方法① 无参构造创建新集合 ②有参构造,传入另一个集合构造新集合
-
有些方法是可选的,如果不实现,应该抛出UnsupportedOperationException
-
一些集合不对元素进行限制,如紧张空元素,会抛出{@code NullPointerException}或{@code ClassCastException}
-
巴拉巴拉有时间再读
package interfacePag;
import java.util.Collection;
/**
* 集合层次结构的根集合,集合包含一组对象(元素)
* 有些集合允许重复元素有些不允许
* 有些集合有序有些无序
* JDK没有提供这个根集合的直接实现吗,而是去实现他的子接口(list, set)
*
* 实现该接口的集合应该实现两个标准构造器
* ①无参构造
* ②有参构造,传入另一个collection构造新collection
*
* 有些方法是可选的,如果不去实现应该抛出@code UnsupportedOperationException}
*
* 有些集合的实现可能对元素加以限制
* ① 对空值的限制 @code NullPointerException}
* ② 对指定类型的限制 {@code ClassCastException}
*
* 每个实现都有自己的同步政策
*
*
* @param <E>
*/
public interface MyCollection<E> extends MyIterable<E> {
/**
* 返回collection的元素个数,如果个数比Integer.MAX_VALUE大则返回nteger.MAX_VALUE
* @return collection的元素个数
*/
int size();
/**
*
* @return {@code true} 如果为空
*/
boolean isEmpty();
/**
*
* @param o element
*
* @return {@code true}如果包含元素o,不直接用泛型E是因为可能不规定泛型
*
* @throws ClassCastException 如果o的类型于Collection所支持的类型不同
*
* @throws NullPointerException 当不支持null但是传入了null
*/
boolean contains(Object o);
/**
* 并不会保证元素的返回顺序,除非规定
*
* @return {@code Iterator}返回迭代器
*/
MyIterator<E> iterator();
/**
* 把集合元素放到新数组返回,注意,返回的是新数组(safe),所以用户可以随意更改
*
* @return Object[]
*/
Object[] toArray();
//剩下还有几个toArray太复杂以后再看吧
/**
*
* @param e
* @return {@code true} 如果成功添加
*
* @throws UnsupportedOperationException 如果不支持add操作
*
* @throws ClassCastException add了collection不支持的类型
*
* @throws NullPointerException add了null,但是collection不支持addnull
*
* @throws IllegalStateException
*
* @throws IllegalArgumentException
*/
boolean add(E e);
/**
* {@code Objects.equals(o, e)}, if
* this collection contains one or more such elements. Returns
* {@code true} if this collection contained the specified element (or
* equivalently, if this collection changed as a result of the call).
*
* @param o element to be removed from this collection, if present
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the type of the specified element
* is incompatible with this collection
* (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this collection
*/
boolean remove(Object o);
/**
* 最简单的方法是依赖 {@code Object.equals}来实现
* 但是有些会覆盖重写这个方法根据情况选择值比较或引用比较
* @param o
* @return
*/
boolean equals(Object o);
//接下来是一些对多个对象进行的操作,这里只写几个
void clear();
boolean addAll(Collection<? extends E> c);
}
MyAbstractCollection
package AbstractPag;
import interfacePag.MyCollection;
import interfacePag.MyIterator;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Iterator;
import static java.util.AbstractCollection.finishToArray;
public abstract class MyAbstractCollection<E> implements MyCollection<E> {
protected MyAbstractCollection() {
}
public abstract MyIterator<E> iterator();
public abstract int size();
/**
* 判断是否为空就是调用size()方法,判断返回值是否为0
* @return
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* 查找元素是否存在
* @param o element
*
* @return
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean contains(Object o){
//使用迭代器遍历,拿到迭代器对象
MyIterator<E> itr = iterator();
//判断是否为空
if(o == null){
while(itr.hasNext()){
if(itr.next() == null){
return true;
}
}
}else {
while (itr.hasNext()){
if(o.equals(itr.next())){
//.equals根据不同的对象可能有不同的重载,可能是值比较也可能是引用比较
return true;
}
}
}
return false;
}
public Object[] toArray(){
//先拿到迭代器,在遍历拷贝到新的数组
//数组的长度可以通过size()获得
int capacity = size();
Object[] array = new Object[capacity];
MyIterator<E> itr = iterator();
for(int i = 0; i < capacity; i++){
//还是要判断是否能取到,因为可能在toArray的过程中其他线程对collection进行了修改
if(!itr.hasNext()){
//拷贝到一个容量更小的数组返回
return Arrays.copyOf(array,i);
}
array[i] = itr.next();
}
//看是否真的遍历完了
//return itr.hasNext() ? finishToArray(array, itr) : array;
if(itr.hasNext()){
//finishToArray(array, itr)
while (itr.hasNext()){
int cap = array.length;
if(capacity == cap){
//会构建一个新的数组,新数组的容量是原来的两倍+1
int newCap = cap + (cap >> 1) + 1;
array = Arrays.copyOf(array,newCap);
}
array[capacity++] = (E)itr.next();
}
}
//因为新数组的容量是原来的两倍+1,所以不一定占满
if(capacity < array.length){
array = Arrays.copyOf(array,capacity);
}
return array;
}
public boolean remove(Object o){
MyIterator<E> itr = iterator();
if(o == null){
while (itr.hasNext()){
if(itr.next() == null){
itr.remove();
return true;
}
}
}else{
while (itr.hasNext()){
if(itr.next().equals(o)){
itr.remove();
return true;
}
}
}
return false;
}
public String toString(){
//应该用可变字符串StringBuilder
MyIterator itr = iterator();
if(!itr.hasNext()){
return "[]";
}else{
StringBuilder sb = new StringBuilder();
sb.append("[");
while (itr.hasNext()){
sb.append(itr.next());
if (! itr.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
return null;
}
}
Mylist接口
package interfacePag;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
/**
* 有序集合,元素在集合有序可以通过下标访问
*
* 允许重复元素
*
* 可以对null进行操作,也可以禁止对null的操作
*
* 这个接口规定了除了{@code Collection} 接口外的其他限制
*/
public interface MyList<E> extends MyCollection<E> {
int size();
boolean isEmpty();
MyIterator<E> iterator();
boolean contains(Object o);
Object[] toArray();
/**
*
* @param e 将e添加到尾部
* @return
* @throws UnsupportedOperationException if the {@code add} operation
* is not supported by this list
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this list
*/
boolean add(E e);
boolean remove(Object o);
MyListIterator<E> listIterator();
/**
*
* @param c 下限通配符用限制类型的下限,通过比较器限制的规则来进行比较
* 策略模式:在运行时可以通过传递不同的比较器选择不同的算法
* <? super E> 准许所以的子类使用相同的父类型的比较器
*/
default void sort(Comparator<? super E>c){
Object[] array = this.toArray();
Arrays.sort(array, (Comparator)c);
MyListIterator itr = this.listIterator();
for(int i = 0; i< array.length; i++){
listIterator().next();
listIterator().set((E) array[i]);
}
}
void clear();
E get(int index);
int indexOf(Object o);
}
这里是使用到了Comparator<? super E>c:下限通配符用限制类型的下限,通过比较器限制的规则来进行比较;
策略模式:在运行时可以通过传递不同的比较器选择不同的算法;