Java笔记---集合(Collection)

集合用来持有一些对象,被持有的对象称为集合中的元素。Collection是集合的最上层接口,定义了一些集合该有的常规操作。

Jdk中提供了一些集合的具体实现,如有序的集合List、不可重复的集合Set。不过Jdk中实现的集合都没有直接实现Collection,而是又定义更具体的接口List和Set。List是有序的可重复的集合,而Set为不可重复的集合。

Jdk建议所有Collection的实现都应该提供一个无参数和一个带Collection参数的构造方法。Collection参数的构造方法用来创建集新的集合并将指定集合的元素都添加到新集合中。

Collection中定义的接口并不要求都实现,对一些不需要的接口建议抛出一个UnsupportedOperationException异常。例如集合是只读的那么在调用add方法时应该抛出该异常。

集合的具体实现可能对元素的类型做出限制,如不允许为nll或只能是特定的类型,作出限制后若将一个类型不正确的元素添加到集合中时建议抛出NullPointerException、ClassCastException或返回false。但这不是必须的,例如向集合中添加一个类型不正确的元素时因为类型不正确,所以并不会被添加也就不会影响到集合,这时返回成功也是可以的,但若调用者不清楚其中的逻辑这反而产生不友好的体验。

Collection

1、增删查

1.1 boolean add(E e);

向集合中添加元素,若集合因为该操作而发生变化则返回true。
若集合中的元素不允许重复且已存在该元素则建议返回false。
除因元素已存在而不进行添加返回false外,其它任何原因拒绝添加都应该抛出异常,从而保证该调用后元素一定存在于与集合中。

1.2 boolean remove(Object o);

从集合中移除指定的元素(可选),若元素在集合中存在则移除则返回true,若不存在则返回false。

1.3 void clear();

清除集合中的所有元素(可选)

1.4 boolean contains(Object o);

若集合中存在指定元素o则放回true。
一般情况下与较集合中的元素进行比较是否相等使用:(o == null ? e == null : o.equals(e)) 的方式比较。

1.5 Iterator<E> iterator();

返回遍历Collection中所有元素的迭代器, 迭代器的顺序由具体的实现决定。

1.6 Object[] toArray();

新建一个包含所有元素的数组并返回

返回的数组都是新建的,对返回的数组的操作(非元素的操作)不会影响到集合,所以该方法是安全的。

1.7 <T> T[] toArray(T[] a);

将集合中的元素拷贝到指定数组a中并返回。若a的长度小于集合中元素的数量则扩展a。

2、批量增删查:

2.1 boolean addAll(Collection<? extends E> c);

将指定集合中的所有元素添加到集合中(可选),若集合因此发生变化则返回true。

2.2 boolean removeAll(Collection<?> c);

移除所有存在于集合c中的元素(可选),若集合因此发生变化则返回true.

2.3 boolean retainAll(Collection<?> c);

保留所有在c中存在的元素,删除c中不存在的元素(可选)。若集合因该调用发生变化则返回true。

2.4 boolean containsAll(Collection<?> c);

若集合c的元素在集合中都存在则返回true

3、集合的状态:

3.1 int size();

返回集合中元素的数量。
如果数量超过Integer.MAX_VALUE,则返回Integer.MAX_VALUE。
Jdk中各个Collection的实现最大数量限制都未超过Integer.MAX_VALUE。

3.2 boolean isEmpty();

如果Collection中一个元素都没有则返回true

4、其它

4.1 boolean equals(Object o);

比较两个集合是否相等。
Collection没有对equals具体要求,但自己实现时因注意到Collection是个集合,同时保证equals相等时hashCode也相等。

4.2 int hashCode();

返回集合的hashCode。Collection没有对hashCode具体要求,但若自己实现了equals方法则也是应该更新hashCode方法,因为一些地方认为equals相等那么hashCode也是相等的。

二、AbstractCollection

AbstractCollection基于iterator()实现了一些通用的方法,但AbstractCollection本身并没有实现iterator()方法。

public abstract class AbstractCollection<E> implements Collection<E> {
    public abstract Iterator<E> iterator();
}
1. public boolean addAll(Collection<? extends E>)

通过多次调用add方法将指定集合中的元素逐个添加。但AbstractCollection并未实现具体add方法。

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}
public boolean add(E e) {
    throw new UnsupportedOperationException();
}
2. public boolean remove(Object o)

通过iterator逐个遍历集合中的元素,查找第一个相等的元素,然后使用iterator的remove方法将其移除,并返回true。AbstractCollection的remove是支持null元素的。

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()) {
            if (o.equals(it.next())) {
                it.remove();
                return true;
            }
        }
    }
    return false;
}
3. boolean removeAll(Collection<?> c)

通过集合的iterator遍历每一个元素,判断元素是否在c集合中,若存在则将其移除。

public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    boolean modified = false;
    Iterator<?> it = iterator();
    while (it.hasNext()) {
        if (c.contains(it.next())) {
            it.remove();
            modified = true;
        }
    }
    return modified;
}
4. boolean retainAll(Collection<?> c)

通过集合的iterator遍历每一个元素,判断元素是否在c集合中,若不存在则将其移除。

public boolean retainAll(Collection<?> c) {
    Objects.requireNonNull(c);
    boolean modified = false;
    Iterator<E> it = iterator();
    while (it.hasNext()) {
        if (!c.contains(it.next())) {
            it.remove();
            modified = true;
        }
    }
    return modified;
}
5. clear()

遍历所有元素,依次移除

public void clear() {
    Iterator<E> it = iterator();
    while (it.hasNext()) {
        it.next();
        it.remove();
    }
}
6. boolean contains(Object o)

通过iterator逐个遍历查找第一个相等的元素并返回true,支持null元素

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;
}
7. boolean containsAll(Collection<?> c)

遍历c中的元素逐个调用contains进行查找,不存在则直接返回false。

public boolean containsAll(Collection<?> c) {
    for (Object e : c)
        if (!contains(e))
            return false;
    return true;
}
8. public Object[] toArray()

创建一个初始大小为size()的新数组,并通过iterator遍历将集合中的元素并添加到该数组中。若iterator返回的数量大于size(),将数组大小扩展未原来的1.5倍+1。
在AbstractCollection中定义了一个最大容量,若大于最大值则取Integer.MAX_VALUE,返回之前通过Arrays.copyOf将多出来的元素去除。

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

public Object[] toArray() {
    Object[] r = new Object[size()];
    Iterator<E> it = iterator();
    for (int i = 0; i < r.length; i++) {
        if (! it.hasNext())
            return Arrays.copyOf(r, i);
        r[i] = it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}

private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
    int i = r.length;
    while (it.hasNext()) {
        int cap = r.length;
        if (i == cap) {
            int newCap = cap + (cap >> 1) + 1;
            if (newCap - MAX_ARRAY_SIZE > 0)
                newCap = hugeCapacity(cap + 1);
            r = Arrays.copyOf(r, newCap);
        }
        r[i++] = (T)it.next();
    }
    return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0)
        throw new OutOfMemoryError
            ("Required array size too large");
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
9. <T> T[] toArray(T[] a)

转化为指定类型的数组时使用指定的数组,若指定数组小于size()则重新分配一个大小为size的数组。若指定数组的大于size,将集合中的值从0填入数组中到则多余的元素填null。

public <T> T[] toArray(T[] a) {
    int size = size();
    T[] r = a.length >= size ? a :
                (T[])java.lang.reflect.Array
                .newInstance(a.getClass().getComponentType(), size);
    Iterator<E> it = iterator();

    for (int i = 0; i < r.length; i++) {
        if (! it.hasNext()) {
            if (a == r) {
                r[i] = null;
            } else if (a.length < i) {
                return Arrays.copyOf(r, i);
            } else {
                System.arraycopy(r, 0, a, 0, i);
                if (a.length > i) {
                    a[i] = null;
                }
            }
            return a;
        }
        r[i] = (T)it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}
11. public boolean isEmpty()

通过seize方法来判断集合是否为空。

public boolean isEmpty() {
    return size() == 0;
}
 public abstract int size();
12. public String toString()

toString调用元素的toString将集合中所有元素拼接到['e1', 'e2']格式的字符串中。

public String toString() {
    Iterator<E> it = iterator();
    if (! it.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = it.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! it.hasNext())
            return sb.append(']').toString();
        sb.append(',').append(' ');
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343