Java 集合(三)

来源:互联网 发布:淘宝模板是什么格式的 编辑:程序博客网 时间:2024/06/07 06:57

四. List 集合

  • List 集合代表一个元素有序、可重复的集合,其中每个元素都有其对应的顺序索引,可以通过索引来访问指定位置的集合元素。

1. Java 8 改进的 List 接口和 ListIterator 接口

  • 作为 Collection 接口的子接口,List 可以使用 Collection 接口中的全部方法。且由于 List 是有序集合,因此 List 集合里增加了一些根据索引来操作集合元素的方法。
    • void add(int index, Object element):将元素 element 插入到 List 集合的 index 处。
    • boolean addAll(int index, Collection c):将集合 c 所包含的所有元素都插入到 List 集合的 index 处。
    • Object get(int index):返回集合 index 索引处的元素。
    • int indexOf(Object o):返回对象 o 在 List 集合中第一次出现的位置索引。
    • int lastIndexOf(Object o):返回对象 o 在 List 集合中最后一次出现的位置索引。
    • Object remove(int index):删除并返回 index 索引处的元素。
    • Object set(int index, Object element):将 index 索引处的元素替换成 element 对象,返回被替换的旧元素。
    • List subList(int fromIndex, int toIndex):返回从索引 fromIndex(包含)到索引 toIndex(不包含)处所有集合元素组成的子集合。
  • 示例程序:

    import java.util.*;public class ListTest {    public static void main(String[] args) {        List books = new ArrayList();        // 向 books 集合中添加三个元素        books.add(new String("禅与摩托车维修艺术"));        books.add(new String("在路上"));        books.add(new String("麦田里的守望者"));        System.out.println(books);        // 将新字符串对象插入在第二个位置        books.add(1, new String("追风筝的人"));        for(int i=0 ; i<books.size() ; i++) {            System.out.println(books.get(i));        }        // 删除第三个元素        books.remove(2);        System.out.println(books);        // 判断指定元素在 List 集合中的位置,输出 1,表明位于第二位        System.out.println(books.indexOf(new String("追风筝的人")));  // ①        // 将第二个元素替换成新的字符串对象        books.set(1,  new String("在路上"));        System.out.println(books);        // 将 books 集合的第二个元素(包括)到第三个元素(不包括)截取成子集合        System.out.println(books.subList(1, 2));    }}输出结果:    [禅与摩托车维修艺术, 在路上, 麦田里的守望者]    禅与摩托车维修艺术    追风筝的人    在路上    麦田里的守望者    [禅与摩托车维修艺术, 追风筝的人, 麦田里的守望者]    1    [禅与摩托车维修艺术, 在路上, 麦田里的守望者]    [在路上]
  • List 判断两个对象相等的标准:只要 equals() 方法比较返回 true 即可。
  • Java 8 还为 List 接口添加了如下两个默认方法:

    • void replaceAll(UnaryOperator operator):根据 operator 指定的计算规则重新设置 List 集合的所有元素。replaceAll() 方法需要一个 UnaryOperator 来替换所有集合元素,UnaryOperator 也是一个函数式接口,可以使用 Lambda 表达式作为参数。
    • void sort(Comparator c):根据 Comparator 参数对 List 集合的元素排序。sort() 方法需要一个 Comparator 对象来控制元素排序,可使用 Lambda 表达式来作为参数。
    • 示例程序:
      import java.util.*;public class ListTest3 {    public static void main(String[] args) {        List books = new ArrayList();        books.add(new String("禅与摩托车维修艺术"));        books.add(new String("追风筝的人"));        books.add(new String("麦田里的守望者"));        books.add(new String("在路上"));        // 使用目标类型为 Comparator 的 Lambda 表达式对 List 集合排序        books.sort((o1, o2) -> ((String)o1).length() - ((String)o2).length());        System.out.println(books);        // 使用目标类型为 UnaryOperatorLambda 表达式来替换集合中所有元素        // 该 Lambda 表达式控制使用每个字符串的长度作为新的集合元素        books.replaceAll(ele -> ((String)ele).length());        System.out.println(books);    }}输出结果:    [在路上, 追风筝的人, 麦田里的守望者, 禅与摩托车维修艺术]    [3, 5, 7, 9]
  • 与 Set 只提供了一个 iterator() 方法不同,List 还提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象,ListIterator 接口继承了 Iterator 接口,提供了专门操作 List 的方法。ListIterator 接口在 Iterator 接口基础上增加如下方法:

    • boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。
    • Object previous():返回该迭代器的上一个元素。
    • void add(Object o):在指定位置插入一个元素。
    • ListIterator 与普通的 Iterator 进行对比,不难发现 ListIterator 增加了向前迭代的功能(Iterator 只能向后迭代),且 ListIterator 还可通过 add() 方法向 List 集合中添加元素(Iterator 只能删除元素)
    • 示范程序:
      import java.util.*;public class ListIteratorTest {    public static void main(String[] args) {        String[] books = {            "禅与摩托车维修艺术", "追风筝的人",            "麦田里的守望者"        };        List bookList = new ArrayList();        for (int i=0 ; i<books.length ; i++) {            bookList.add(books[i]);        }        ListIterator lit = bookList.listIterator();        while(lit.hasNext()) {            System.out.println(lit.next());            lit.add("-----分隔符-----");        }        System.out.println("=====下面开始反向迭代=====");        while(lit.hasPrevious()) {            System.out.println(lit.previous());        }    }}输出结果:    禅与摩托车维修艺术    追风筝的人    麦田里的守望者    =====下面开始反向迭代=====    -----分隔符-----    麦田里的守望者    -----分隔符-----    追风筝的人    -----分隔符-----    禅与摩托车维修艺术

2. ArrayList 和 Vector 实现类

  • ArrayList 和 Vector 完全支持前面介绍的 List 接口的全部功能
  • ArrayList 和 Vector 类都是基于数组实现的 List 类,它们封装了一个动态的允许再分配Object[] 数组
    • ArrayList 或 Vector 对象使用 initialCapacity 参数来设置该数组的长度
    • 向 ArrayList 或 Vector 中添加元素超出了该数组的长度时,它们的 initialCapacity 会自动增加。
    • 如果向 ArrayList 或 Vector 集合中添加大量元素时,可使用 ensureCapacity(int minCapacity) 方法一次性地增加 initialCapacity。这可以减少重分配次数,提高性能。
    • 如果开始就知道 ArrayList 或 Vector 集合需要保存多少个元素,可以在创建它们的时候就指定 initialCapacity 大小。如果创建空的 ArrayList 或 Vector 集合时不指定 initialCapacity 参数,则 Object[] 数组的长度默认为 10。
    • 除此之外,ArrayList 或 Vector 集合还提供了如下两个方法来重新分配 Object[] 数组:
      • void ensureCapacity(int minCapacity):将 ArrayList 或 Vector 集合的 Object[] 数组长度增加大于或等于 minCapacity 值。
      • void trimToSize():调整 ArrayList 或 Vector 集合的 Object[] 数组长度为当前元素的个数。调用该方法可减少 ArrayList 或 Vector 集合对象占用的存储空间。
  • Vector 是一个古老的集合,里面有一些功能重复的方法。其中方法名更短的是后来新增的,方法名更长的方法则是 Vector 原有的方法。Vector 有很多缺点,尽量少用 Vector 实现类
  • ArrayList 和 Vector 的显著区别:
    • ArrayList 是线程不安全的。多个线程访问同一个 ArrayList 集合时,如果有超过一个线程修改了 ArrayList 集合,则程序必须手动保证该集合的同步性。
    • Vector 是线程安全的。正是由于这一点,Vector 的性能比 ArrayList 的性能要低。
    • 实际上,即使要保证 List 集合线程安全,也不推荐使用 Vector 的实现类。可以使用 Collections 工具类,将一个 ArrayList 变成线程安全的。
  • Vector 还提供了一个 Stack 子类,用于模拟“栈”这种数据结构。“栈”是指“后进先出”(LIFO)的容器。最后被“push”进栈的元素,将最先被“pop”出栈。与 Java 中的其他集合一样,进栈出栈的都是 Object,从栈中取出元素后往往要进行强制类型转换(除非你使用的是 Object 具有的操作)。Stack 类里提供了如下方法:
    • Object peek():返回栈的第一个元素,但并不将该元素 pop 出栈
    • Object pop():返回栈的第一个元素,并将其 pop 出栈。
    • void push(Object item):将一个元素 push 进栈,最后一个进栈的元素总是位于栈顶。
    • Stack 继承了 Vector,也是比较古老的集合类,同样线程安全、性能较差。我们要尽量避免使用 Stack 类。如果要用到“栈”这种数据结构,可以考虑使用 ArrayDeque。

3. 固定长度的 List

  • Arrays.ArrayList 是 Arrays 的内部类 ArrayList 的实例。它是一个固定长度的 List 集合,程序只能遍历访问该集合里的元素,不可增加、删除该集合里的元素,否则会引发 UnsupportedOperationException 异常。
原创粉丝点击