优秀的编程知识分享平台

网站首页 > 技术文章 正文

「Java」从interface出发学习集合

nanyue 2024-10-08 05:38:12 技术文章 6 ℃

一、什么是集合

1.广义上的概念

集合,简称集,是数学中一个基本概念,也是集合论的主要研究对象。集合论的基本理论创立于19世纪,关于集合的最简单的说法就是在朴素集合论(最原始的集合论)中的定义,即集合是“确定的一堆东西”,集合里的“东西”则称为元素。现代的集合一般被定义为:由一个或多个确定的元素所构成的整体
——百度百科

集合就是包含了一堆确定的元素的整体。

2.在java中的概念

集合是一种存放对象的数据结构。

主要分为三类:

  1. List集合:元素存放有序,可以重复
  2. Set集合:元素存放无序,不可重复
  3. Map集合:按key-value对存储,key不能重复,value可重复

接口


这不是全部接口和实现类,但是这是我们主要的研究对象。

二、接口介绍

1.Iterator(迭代器)

代码

为了节省篇幅,我把注释都删了。

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

补充说明

  1. 这个是一个迭代器,一般都会存在与有序的集合类的内部,通过 iterator() 这个方法创建,而返回的对象一般都是实现了这个接口的对象。
  2. 通过这个迭代器的hasNext()方法,可以实现对集合进行遍历操作。

实现类

一般是在实现了List接口、Set接口的实现类中,作为内部类存在。

2.Iterable

代码

在Collection接口中,就实现了这个接口。

public interface Iterable<T> {
	/**
	这是一个Iterator迭代器的构建方法
	*/
    Iterator<T> iterator();
    /**
    这是一个循环遍历的方法,经常写代码的话就会认识了
    不过这里的action我看的不是很懂
    */
    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);
    }
}

补充说明

  1. 这是一个迭代器的构建器,实现这个接口,就可以实现获取相应迭代器的功能
  2. 只要实现了Iterable这个接口,就可以使用java对forEach封装的for(:)循环
  3. Iterable是对Iterator的一个封装,这样就能更好地在不同的实现类中实现不同的迭代器构建方法

3.Collection

代码

代码太多了,一些看方法名就能知道它要实现什么功能的,我就不解释了

public interface Collection<E> extends Iterable<E> {
	/**
	将size返回,为了符合JavaBean的编程思想
	*/
    int size();
	  /**
	需要实现的功能
	判断集合是否为空
	*/
    boolean isEmpty();
	/**
	需要实现的功能
	判断集合中是否存在这个元素
	*/
    boolean contains(Object o);

    Iterator<E> iterator();
	/**
	需要实现的功能
	将当前集合转化成数组并返回
	*/
    Object[] toArray();
	/**
	需要实现的功能
	将当前集合转化成数组,如果有传入参数,就将数组赋值给传入的参数
	如果没有传入,就直接返回
	*/
    <T> T[] toArray(T[] a);

    boolean add(E e);

    boolean remove(Object o);
	/**
	需要实现的功能
	判断集合中是否存在这个集合中的全部元素
	*/
    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);
	/**
	需要实现的功能
	删除集合中和传入集合相同的元素,
	*/
    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);
	/**
	《Object中的方法
	*/
    void clear();

    boolean equals(Object o);

    int hashCode();
	/**
	Object中的方法》
	*/
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    /**
    Stream跟mysql中的视图类似,它占用内存小
    这个方法就是将该集合的视图返回
    */
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    /**
    是多线程的stream方法
    相比与stream()的区别就是,在遍历的时候,它是采用多线程的方式
    */
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

补充说明

  1. Collection的实现类的实例对象,在使用remove时,避免在在forEach,for(:)中使用集合本身的remove方法,在这几个循环中会使用该迭代器,如果直接在集合上删除的话,会出发接口实现类(Arraylist)上的checkForComodification方法报错
  2. removeIf是用来弥补remove的一种方法,可以在forEach,for(:)中使用
  3. Stream在使用时只能遍历一次,是一种声明式的数据处理方式,Stream不会存储元素,在遍历时按需计算。

4.List(有序集合)

代码

因为这些接口中存在实现,重复的方法我就不重复的复制了

public interface List<E> extends Collection<E> {
	/**
	这个是实现替换功能,这个替换不是直接替换
	而是需要传入一个替换规则,根据规则替换
	貌似只有基本数据类型才能使用
	*/
	default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }
    /**
    对集合进行排序,根据Comparator里面的compare方法的实现进行排序
    */
    @SuppressWarnings({"unchecked", "rawtypes"})
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
    /**
    需要实现功能
    获取指定下标的对象
    */
    E get(int index);
    /**
    需要实现功能
    获取传入对象的所在的第一个下标
    */
    int indexOf(Object o);
    /**
    需要实现功能
    获取传入对象的所在的最后一个下标
    */
    int lastIndexOf(Object o);
    /**
    需要实现功能
    返回一个list迭代器
    这个迭代器能是双向迭代器
    */
    ListIterator<E> listIterator();
     /**
    需要实现功能
    根据传进来的参数,返回一个以参数为下标的对象开始的list迭代器
    */
    ListIterator<E> listIterator(int index);
     /**
    需要实现功能
    返回一个以formIndex开始,toIndex-1结尾的list
    */
    List<E> subList(int fromIndex, int toIndex);
}

补充说明

  1. indexOf的方法,需要根据实现类的具体实现来确定,对比的是地址,还是内容。
  2. get方法获得的只是对象的地址

实现类

  1. LinkedList

LinkedList是基于链表实现的,也继承了链表的特点,增删快,查询慢

  1. ArrayList

ArrayList是基于数组实现的,也继承了数组的特点,查询快,增删慢。

  1. Vector

Vector是基于数组实现的,跟ArrayList类似,很多实现方法也是类似的,但是Vector是线程安全的,因为它的方法加了synchronized关键字。

5.Set(无序集合)

代码

public interface Set<E> extends Collection<E> {
	/**
	这个接口的方法跟Conlection接口的一模一样,可能只是改了注释,做了一下接口实现的描述,我也看不懂,方法体里面是空的,也没有新方法。。
	*/
}

实现类

  1. HashSet

HashSet是基于哈希表实现的,它的构建方法会创建一个HashMap对象,用来存放对象。HashSet除了无序之外,还不能有重复的值。存取都快。

public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

这是HashSet的方法,从这里来看,HashSet是将对象当作Key存入HashMap中,所以才不能有重复值。

  1. TreeSet

TreeSet是基于二叉树实现的,不允许重复,不允许null,无序。存取效率比HashSet低。

  1. LinkedHashSet

LinkedHashSet是基于链表和哈希表(HashMap)实现的,这个和上面两个不同,它是有序的,存取效率比HashSet低。

6.Map(映射)

Map接口的代码太长了,就不在这里做解释了,有兴趣的话自己去看吧。

实现类

  1. HashMap

HashMap是基于hash算法、数组、二叉树实现的,插入快,查询快,什么都快。

  1. TreeMap

TreeMap是基于hash算法和二叉树实现的,插入慢,查询慢。

——————————————————————————————
如果本文章内容有问题,请直接评论或者私信我。
未经允许,不得转载!
第一次写这么长的文章,快写崩溃了,估计内容会出很多问题,也不是特别全,实现类的内容就不想写了。

最近发表
标签列表