Java数据结构(2)

集合和数组的区别

a. 数组长度不可改变且无法保存具有映射关系的数据;
集合用于保存数量不确定的数据,以及保存具有映射关系的数据。
b. 数组元素既可以是基本类型的值,也可以是对象;集合只能保存对象。

数组与集合的特点

数组:
a. 长度固定,如果要扩容需要程序员自己维护,插入和删除效率很低;
b. 数组只支持有序,可重复的特点,但实际开发中,可能需要无序,不可重复的需求;
集合:
a. 长度不固定,可扩容;
b. 支持多种数据的存储结构,有序,无序可重复,不可重复,一对一,一对多;
c. jdk在数组和链式的基础上设计了很多有用的容器;

Collection

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的子接口如List和Set。

Collection

通过继承Iterable迭代器遍历整个集合。


Iterable接口中的方法
// 返回一个在一组T类型的元素上进行迭代的迭代器
// 返回一个实现Iterator接口的对象
Iterator<T> iterator();

// 存在一个默认实现,用来遍历Iterable中的所有元素
default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
}

// 返回一个Spliterator,对元素进行分割
default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
Iterable
// 如果迭代器中还有元素则返回true
boolean hasNext();

// 返回迭代器中游标的下一元素
E next();

// 将迭代器新返回的元素删除。
// 从迭代器指向的collection中移除迭代器返回的最后一个元素,每次调用next后只能调用一次此方法,如果进行迭代时调用此方法之外的其他方式修改改迭代器所指向的collection,则迭代器的行为是不确定的。
default void remove() {
        throw new UnsupportedOperationException("remove");
}

// 使用Lambda表达式来遍历集合元素
default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
}
Iterator与Iterable

Iterable是集合框架的超级接口,Iterable是jdk1.5引入的新特性,Iterator在jdk1.2就有了,都是为了迭代创造的,Iterable只是包装了Iterator,进而允许实现此接口的对象成为foreach语句的目标,即实现类Iterable接口的类可以拥有增强的for循环,言外之意只要实现了Ierable接口的类,就可以使用Iterator迭代器。
为什么不直接将hasNext(),next()放到Iterable接口中,那样的话其他类直接实现就ok了?
因为有些集合类可能不止一种遍历方式,实现Iterable的类可以在试下多个Iterator内部类,例如:LinkedList中的ListItr和DescendingIterator两个内部类,分别实现了双向遍历和逆序遍历,通过返回不同的Iterator实现不同的遍历方式,更加灵活。如果将两个接口合并,则无法返回不同的Iterator实现类了。


Collection
// 返回集合中元素的个数
int size();

// 判断集合是否为空,为空返回true
boolean isEmpty();

// 判断集合中是否包含指定的元素,存在返回true
boolean contains(Object o);

// 返回用于遍历的迭代器
Iterator<E> iterator();

// 将集合转换为数组
Object[] toArray();

// 将指定集合转变成对应的数组
<T> T[] toArray(T[] a);

// 添加一个元素,成功返回true
boolean add(E e);

// 移除一个元素,成功返回true
boolean remove(Object o);

// 判断集合汇总是否包含指定的集合元素,成功返回true
boolean containsAll(Collection<?> c);

// 添加一个集合的元素,成功返回true
boolean addAll(Collection<? extends E> c);

// 移除一个集合的元素,成功返回true
boolean removeAll(Collection<?> c);

// 删除满足给定条件的集合的所有元素,成功返回true
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;
    }

// 两个集合的交集
boolean retainAll(Collection<?> c);

// 移除所有元素
void clear();

// 比较对象与集合中的元素
boolean equals(Object o);

// 返回此集合的哈希码值
int hashCode();

// 并行迭代器,这个方法是继承自Iterable接口
@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);
    }

Spliterator是一个可分割迭代器(splitable iterator)。jdk1.8发布后,对于并行处理的能力大大增强,Spliterator就是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator。
Stream是元素的集合,这点让Stream看起来用些类似Iterator;可以支持顺序和并行的对原Stream进行汇聚的操作,可以认为是一个高效的Iterator把对集合的操作变成了对流的操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。