Java源码学习之集合系列二

AbstractCollection

本系列的Java源码版本是官网最新版java 11

在使用容器之前,首先需要熟悉一个概念 迭代器 ,不只是Java语言有这样的概念,其他的语言,比如python、C++等面向对象的语言中都有这些概念。迭代器是容器的基础

In computer programming, an iterator is an object that enables a programmer to traverse a container, particularly lists.

维基百科上意思:迭代器 就是能让编程者遍历容器的对象,特别是List

contains

	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;
	}

从代码上看,可以发现容器2个特点

  • 可以存放null对象
  • 判断对象相等是通过对象的equals方法

这里有一个代码处理上的小细节,当 o != null 判断对象相等的时候 o.equals(it.next()) o对象放在前面,这样的好处是防止 NullPointerException 。在日常开发过程中经常会碰到这个问题,使用这个小技巧可以在一定程度上避免此类问题发生

代码示例

	package com.jaksona;
	public class Main {
	    public static void main(String[] args) {
		    // write your code here
	        MyUnmodifiedCollection c1 = new MyUnmodifiedCollection(1);
	        System.out.println(c1.contains(1)); 
	        // 输出 true 因为对象Integer重写了equals方法
	
	        MyUnmodifiedCollection c2 = new MyUnmodifiedCollection(new MyCustomInteger(1));
	        System.out.println(c2.contains(new MyCustomInteger(1))); 
	        // 输出 false 因为对象MyCustomInteger未重写了equals方法
	    }
	}

MyInteger 类里面就是存储了一个int成员变量,你会发现同样是数字1输出的结果是不一样的,原因就是 Integer 官方已经实现了 equlashashCode 方法。可能你会对前面的那两条语句有点困惑,数字1为啥变成了Integer,这个后续会跟大家说,这里涉及到一个java 1.5引入的概念 装箱(boxing)和拆箱(unboxing) ,因为集合里面都是存储对象,所有基本类型char、int、long等等都会自动包装成对应的引用对象

remove

remove方法跟contains基本一样,只是在返回值前增加了一行Iterator的remove方法调用

removeAll和retainAll

    /**
     * 与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;
    }
    /**
     * 与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;
    }

这俩方法是常用的集合与集合之间的运算
示意图

toArray

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

该方法有个特点,如果另一个线程在操作iterator(前提是支持多线程操作)也可以保证返回的数组是最新的,这个特性是在 finishToArray 中实现的
这里有一个优化细节处理,如果iterator元素个数少于size会直接返回copy数组

toArray

	public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        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()) { // fewer elements than expected
                if (a == r) {
                    r[i] = null; // null-terminate
                } 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();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

该方法与上面的方法是重载的关系,返回指定类型的数组。日常开发过程中我们常常需要将一个List转换成数组,这个时候就可以使用这两个方法了。
示意图

总结

AbstractCollection实现了集合基本操作,比如contains、remove、containsAll、addAll,还有集合之间的操作removeAll、retainAll

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值