Java基础之Collections框架List接口及其源码分析

    技术2022-07-11  87

    Java基础之Collections框架List接口及其源码分析

    List接口的特点索引访问搜索迭代范围视图 List简单实例List源码分析 有序集合(也称为序列)。 用户可以精确控制列表中每个元素的插入位置。 用户可以通过其整数索引(列表中的位置)访问元素,并在列表中搜索元素。 与集合不同,列表通常允许重复的元素。 更正式地说,列表通常允许成对的元素e1和e2,使得e1.equals(e2),并且如果它们完全允许空元素,则它们通常允许多个空元素。 List接口在Iterator的协定,add,remove,equals和hashCode方法的协定上放置了除Collection接口中指定的规定以外的其他规定。 为了方便起见,还包含其他继承方法的声明。 List接口提供了四种位置(索引)访问列表元素的方法。 列表(如Java数组)从零开始。 请注意,对于某些实现(例如LinkedList类),这些操作可能在时间上与索引值成比例执行。 因此,如果调用者不知道实现,则遍历列表中的元素通常比对其进行索引更可取。 List接口提供了一个称为ListIterator的特殊迭代器,除了Iterator接口提供的常规操作之外,该迭代器还允许元素插入和替换以及双向访问。 提供一种获取列表迭代器的方法,该列表迭代器从列表中的指定位置开始。 List接口提供了两种搜索指定对象的方法。 从性能的角度来看,应谨慎使用这些方法。 在许多实现中,它们将执行昂贵的线性搜索。 List接口提供了两种方法,可以有效地在列表中的任意点插入和删除多个元素。 注意:虽然允许列表将自身包含为元素,但建议格外小心:equals和hashCode方法在这样的列表上不再定义良好。

    List接口的特点

    索引访问

    根据元素在列表中的数字位置操作元素。 这包括诸如get,set,add,addAll和remove之类的方法。 //获取元素 索引从0开始 int index = 0; list.get(index);

    搜索

    在列表中搜索指定的对象并返回其数字位置。 搜索方法包括indexOf和lastIndexOf。 String index= “tony”; list.indexOf(index); //获取tony元素的下标

    迭代

    扩展Iterator语义以利用列表的顺序性质。 ListIterator方法提供了此行为。 public int indexOf(E e) { for (ListIterator<E> it = listIterator(); it.hasNext(); ) if (e == null ? it.next() == null : e.equals(it.next())) return it.previousIndex(); // Element not found return -1; }

    范围视图

    子列表方法对列表执行任意范围操作。 int fromIndex = 1,toIndex = 5; list.subList(fromIndex, toIndex)

    Java平台包含两个通用的List实现。ArrayList通常是性能更好的实现,而LinkedList在某些情况下性能更好。像Set接口一样,List增强了对equals和hashCode方法的要求,因此可以比较两个List对象的逻辑相等性,而不必考虑它们的实现类。 如果两个List对象包含相同顺序的相同元素,则它们相等。

    List简单实例

    交换list中指定位置的值 //i和j是list中要替换元素的下标 public static <String> void swap(List<String> a, int i, int j) { String tmp = a.get(i); a.set(i, a.get(j)); a.set(j, tmp); } //将list中的元素打乱 public static void shuffle(List<String> list, Random rnd) { for (int i = list.size(); i > 1; i--) swap(list, i - 1, rnd.nextInt(i)); } public static void main(String[] args) { if (args.length < 2) { return; } int numHands = Integer.parseInt(args[0]); int cardsPerHand = Integer.parseInt(args[1]); String[] suit = new String[] { "spades", "hearts", "diamonds", "clubs" }; String[] rank = new String[] { "ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "jack", "queen", "king" }; List<String> deck = new ArrayList<String>(); for (int i = 0; i < suit.length; i++) for (int j = 0; j < rank.length; j++) deck.add(rank[j] + " of " + suit[i]); //Collections集合处理类 Collections.shuffle(deck); if (numHands * cardsPerHand > deck.size()) { System.out.println("Not enough cards."); return; } for (int i = 0; i < numHands; i++) System.out.println(dealHand(deck, cardsPerHand)); } public static <E> List<E> dealHand(List<E> deck, int n) { int deckSize = deck.size(); List<E> handView = deck.subList(deckSize - n, deckSize); List<E> hand = new ArrayList<E>(handView); handView.clear(); return hand; }

    List源码分析

    public interface List<E> extends Collection<E> { /** 返回list中的元素个数 */ int size(); /** 判断list是否为空 */ boolean isEmpty(); /** 返回list是否包含指定的元素 */ boolean contains(Object o); /** 返回迭代器 */ Iterator<E> iterator(); /** 将list转换为数组 */ Object[] toArray(); /** 返回指定类型的数组 */ <T> T[] toArray(T[] a); /** 添加元素 */ boolean add(E e); /** 移除元素 */ boolean remove(Object o); /** 是否包含指定集合中的所有元素 */ boolean containsAll(Collection<?> c); /** 添加指定集合中的所有元素到list中 */ boolean addAll(Collection<? extends E> c); /** 在指定的位置将指定集合中的元素添加到list中 */ boolean addAll(int index, Collection<? extends E> c); /** 移除指定集合中在list中的所有元素 */ boolean removeAll(Collection<?> c); /** removeAll取反 */ boolean retainAll(Collection<?> c); /** 用将该运算符应用于该元素的结果替换此列表中的每个元素。 */ default void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); //通过迭代器遍历替换 同时operator获取元素 final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } } /** */ @SuppressWarnings({"unchecked", "rawtypes"}) default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); //将list转为数组,通过Arrays的sort方法进行排序 Arrays.sort(a, (Comparator) c); //进行迭代器进行迭代设置值达到排序 ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } } /** 清除list中的所有元素 */ void clear(); /** 比较list是否相等 个数和包含的元素 */ boolean equals(Object o); /** 返回list的hash值,将list中的每一个元素的hashCode进行相加 */ int hashCode(); /** 获取指定位置的元素 */ E get(int index); /** 给指定的索引设置值 */ E set(int index, E element); /** 向指定的位置添加一个元素 */ void add(int index, E element); /** 移除指定索引下的元素 */ E remove(int index); /** 返回元素的list中的索引 */ int indexOf(Object o); /** 返回相关元素最后出现的索引值 */ int lastIndexOf(Object o); /** 返回list特殊的List迭代器 */ ListIterator<E> listIterator(); /** 返回此列表中元素的列表迭代器(正确序列),从列表中的指定位置开始。 */ ListIterator<E> listIterator(int index); /** 返回指定位置之间此列表部分的视图 fromIndex (含)和toIndex(不包含) 如果相等将返回一个空的list 返回的列表由该列表支持,因此是非结构化的返回列表中的更改会反映在此 列表中,反之亦然。返回的列表支持所有支持的可选列表操作通过此列表 */ List<E> subList(int fromIndex, int toIndex); /** 返回一个Spliterator实例 */ @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, Spliterator.ORDERED); } }

    相关的方法的实现是通过List的两个实现类ArrayList,LinkedList去实现的。默认方法 relaceAll和sort是jdk 8中支持的语法。这个是在List接口中实现。里面涉及了Collections类和Arrays类,这个可以认为是集合操作的相关工具类。到时候研究,哈哈!

    Processed: 0.012, SQL: 12