CodeGym /Java 博客 /China /Java 列表
作者
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

Java 列表

已在 China 群组中发布
Java 集合框架包含非常有用的接口和类,实现它们便可处理数据结构。可以说,这是最重要的 JDK 框架之一。List 接口广受欢迎。因为在编程中不需要各种各样的列表,List 接口是必不可少的。在本文中,我们将介绍此接口、Java List 方法和实现。

Java List 接口

列表最重要的一点是它是一个有序的集合。你也可以称之为序列。在 Java 中,列表是同构的,也就是说,列表的元素是相同的数据类型。Java List 接口继承自 Collection,继承了后者的所有操作。除此之外,在 List 中还可以进行以下操作:
  • 位置访问。每个元素都有一个索引,可以根据它们的位置在列表中进行操作。也就是说,你可以添加、排除和修改元素。
  • 搜索。你可以通过内容在列表中找到一个元素并返回它的索引。
  • 迭代。List 所具有的序列性质允许使用迭代方法 (listIterator)。
  • 视野范围。子列表方法在列表上执行任意范围的操作。

Java List 方法

上述操作在 Java List 接口的方法中公开。下面列出了其中的一些方法:
方法 说明
add(E element) 此方法将 element 元素添加到列表的末尾。
add(int index, element) 方法在列表中的特定索引处添加元素。如果传递了所需的参数,它会在列表末尾添加元素。
addAll(int index, Collection collection) 将给定集合中的所有元素添加到列表中。如果传递一个参数,它将给定集合的所有元素添加到列表的末尾。
size() 返回列表的大小(列表中元素的数量)。
get(int index) 返回指定索引处的元素。
set(int index, element) 用新元素替换给定索引处的元素,并返回被新元素替换的元素。
remove(int index) 从指定索引中移除元素。
remove(element) 移除列表中给定元素的第一个匹配项。
clear() 从列表中移除所有元素。
indexOf(element) 返回给定元素的第一个匹配项。如果元素不在列表中,则返回 -1
lastIndexOf(element) 返回给定元素的最后一个匹配项。如果元素不在列表中,则返回 -1
equals(element) 比较给定元素与列表元素的相等性。
hashCode() 返回给定列表的哈希值。
isEmpty() 检查列表是否为空。如果列表为空,则返回 true。
contains(element) 检查列表是否包含元素。如果列表包含元素,则返回 true。
containsAll(Collection collection) 检查列表是否包含所有元素的集合。
sort(Comparator comp) 根据给定的比较器对列表中的元素进行排序。
subList(int fromIndex, int toIndex) 返回此列表在指定的 fromIndex(含)到 toIndex(不含)之间部分的视图。

List 实现

因为 List 是一个接口,程序需要创建它的具体实现。你可以在 Java Collections API 的以下 List 实现中进行选择:
  • java.util.ArrayList
  • java.util.LinkedList
  • java.util.Vector
  • java.util.Stack
List 接口最常用的实现称为 ArrayList。虽然不太常见,但你仍然可以在实际任务中看到 LinkedList 的使用,不过,Vector 和 Stack 实际上已过时很久了,因此你很可能只会在具有古老遗留代码的项目中找到它们。

List 接口声明

你可以通过以下方式之一在 Java 程序中声明 List:

List<String> myList = new ArrayList();
List myList1 = new ArrayList();
List myList3 = new ArrayList<String>();
ArrayList arrayList = new ArrayList();
最好通过一个接口声明一个新的列表。类似地,你可以声明 List 的其他实现。 最短的方法:

Vector myVector = new Vector;
LinkedList linkedList = new LinkedList();
Stack stack = new Stack();
通过这种声明,这种列表的元素的数据类型在列表的初始化期间被确定,也就是当元素被添加到那里时被确定。

List myList = new ArrayList<String>();
Vector myVector = new Vector();
LinkedList linkedList = new LinkedList();
Stack stack = new Stack();
stack.add("Paul");
linkedList.add(1);
myVector.add(1.2f);
myList.add('a');
现在,只有字符串可以添加到堆栈中,整数可以添加到 linkedList,浮点数可以添加到 myVectormyList 是一个字符列表。

ArrayList 的工作方式?

如果你已经熟悉了常规数组,那么你对 ArrayList 也有点熟悉了。其实 ArrayList 是一个动态数组,内部是一个普通数组。该数组充当数据存储。ArrayList 只存储引用类型、任何对象,包括第三方类、字符串、输出流和其他集合。包装类用于在 ArrayList 中存储原始数据类型。 在创建列表时,我们可以立即设置其大小,但在大多数情况下不会这样做。默认情况下,ArrayList size = 10。 向 ArrayList 中添加新元素是什么样子的?首先,开始检查内部数组中是否有足够的空间,以及是否还有一个元素适合。如果有空间,新元素将被添加到列表的末尾,即最后一个元素后面的单元。它的索引将是 arraylist.size()。 如果我们刚刚创建了列表,它是空的,这意味着 arrayList.size() = 0。因此,新元素将被添加到索引为 0 的单元中。如果没有足够的空间,在 ArrayList 中创建一个新数组,大小为(旧数组的大小* 1.5)+ 1。根据同样的原理,插入是在列表中间进行的,但同时,插入元素之后的所有元素都向右移动。因此,如果数组中有 5 个元素,需要将一个元素插入到第 2 个单元(即第三个)中,那么 0 和 1 数组元素保留在原位,一个新元素出现在第 2 个单元中,它的前身进入第三个单元中,依此类推。

Java List 示例(Arraylist 实现)


import java.util.*;

public class ArrayListExample2 {
   public static void main(String[] args) {
       List<String> myFriendsList = new ArrayList();
       //we created list of some objects 
       System.out.println( "the size of myList before init = " + myFriendsList.size());
       myFriendsList.add("Alex");
       myFriendsList.add("Tanya");
       myFriendsList.add("Veloxy");
       myFriendsList.add("Alex");
       myFriendsList.add("Andrew");
       System.out.println(myFriendsList);
       System.out.println( "the size of myList after init = " + myFriendsList.size());

       myFriendsList.add("Ihor");
       System.out.println(myFriendsList);
       System.out.println("the size of my list = " +  myFriendsList.size());


       //here the program will print out the first appearance of "Alex" element
       System.out.println(myFriendsList.indexOf("Alex"));
       //program will print out the first appearance of "Alex" element starting from the element 0

       myFriendsList.remove(3);
       System.out.println(myFriendsList.get(3));
       System.out.println("after removing one of Alex's there is only one Alex: " + myFriendsList);
       System.out.println(myFriendsList.get(1));



       myFriendsList.clear();
       System.out.println("the size of the vector after clear method = " +  myFriendsList.size());

   }
}
以下是此程序的输出:
初始化之前 myList 的大小 = 0 [亚历克斯, 塔尼娅, 麦乐可斯, 亚历克斯, 安德鲁] 初始化之后 myList 的大小 = 5 [亚历克斯, 塔尼娅, 麦乐可斯, 亚历克斯, 安德鲁, 伊戈尔] 我的列表的大小 = 6 0 安德鲁 在移除其中一个亚历克斯后,只存在一个亚历克斯:[亚历克斯, 塔尼娅, 麦乐可斯, 安德鲁, 伊戈尔] 塔尼娅 清除方法后向量的大小 = 0 进程完成并出现退出代码 0

LinkedList 的工作方式?

在 LinkedList 中,元素实际上是同一链中的链接。每个元素除了存储的数据之外,都有一个指向上一个元素和下一个元素的链接。这些链接允许你从一个元素导航到另一个元素。迭代器支持双向遍历。实现在列表的开头、中间和结尾的获取、移除和插入的方法。允许你添加任何元素,包括 null。 LinkedList 实现了两个接口 — 不仅是 List,还有 Deque。这提供了从任何元素(甚至是 null)创建双向队列的能力。放在链表中的每个对象都是一个节点 (node)。每个节点包含一个元素,一个指向上一个节点和下一个节点的链接。事实上,链表由一系列节点组成,每个节点都被设计用来存储一个在创建时定义的类型的对象。

代码示例


import java.util.*;
public class LinkedListTest {

       public static void main(String args[]){

           List myLinkedList= new LinkedList<Integer>();
           myLinkedList.add(1);
           myLinkedList.add(2);
           myLinkedList.add(4);
           System.out.println("three added elements: " + myLinkedList);
           myLinkedList.add(5);
           myLinkedList.remove(1);
           System.out.println(myLinkedList);
           myLinkedList.size(); //3
           
           //add new element at the specified position:
           myLinkedList.add(2,7);
           System.out.println(myLinkedList);
                }
       }
输出如下所示:
三个添加的元素:[1, 2, 4] [1, 4, 5] [1, 4, 7, 5]

Vector 代码示例

Vector 也是一个动态数组实现,与 ArrayList 很相似,但是同步的,并且有一些集合框架没有包含的遗留方法。下面是这个类用法的一个简单例子。

import java.util.Vector;

public class VectorExample1 {

   public static void main(String[] args) {
       Vector vector = new Vector();
       System.out.println("the size of the empty vector = " +  vector.size());
       vector.add("Alex");
       vector.add("Tanya");
       vector.add("Andrew");
       System.out.println(vector);
       vector.add("Alex");
       vector.add("Ihor");
       System.out.println(vector);
       System.out.println("the size of the vector = " +  vector.size());
       System.out.println("the first element of the vector = " + vector.firstElement());

       //here the program will print out the first appearance of "Johnny" element
       System.out.println(vector.indexOf("Andrew"));
       //program will print out the first appearance of "Johnny" element starting from the element 1
       System.out.println(vector.indexOf("Alex", 1));
       System.out.println(vector);
       vector.clear();
       System.out.println("the size of the vector after clear method = " +  vector.size());

   }
}
输出是:
空向量的大小 = 0 [亚历克斯, 塔尼娅, 安德鲁] [亚历克斯, 塔尼娅, 安德鲁, 亚历克, 伊戈尔] 向量的大小 = 5 向量的第一个元素 = " + 亚历克斯 2 3 [亚历克斯, 塔尼娅, 安德鲁, 亚历克, 伊戈尔] 清除方法后向量的大小 = 0 进程完成并出现退出代码 0

Java Stack 类代码示例


import java.util.Stack;

public class StackTest {
   public static void main(String[] args) {
       Stack stack = new Stack();
       System.out.println(stack.isEmpty());
       stack.add("Paul");
       stack.add("Johnny");
       stack.add("Alex");
       System.out.println(stack.isEmpty());
       stack.push("Andrew");
       System.out.println(stack);
       stack.pop();
       System.out.println(stack);
   }
}
Stack不仅有 add()remove() 方法,还有 push 和 pop 方法,它们是这种数据结构的经典方法。堆栈遵循“先进后出”的规则,这是一种反队列。因此,pop 操作弹出最后放置在堆栈上的元素。 下面是我们示例的输出:
true false [保罗, 约翰尼, 亚历克斯, 安德鲁] [保罗, 约翰尼, 亚历克斯]
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION