JAVA List 详细介绍

JAVA List 详细介绍

目录

什么是List

List的特点 (不重要)

如何创建List

List常用方法

区别

ArrayList&LinkedList

Vector

Stack

与Arrays类的联系

小细节

什么是List

继上一篇JAVA Arrays类 详细介绍之后

List:列表类型,表示一个有序集合。 Map:映射类型,表示键值对的集合。 Set:集合类型,表示一组不重复的元素。

以上就是接下来几篇的内容,本篇主要是List

List

├── ArrayList

├── LinkedList

└── Vector——Stack

以上是List接口的几个实现类,以下,则是一些不太常用的List可以先略过,Stack应该还算常用,后面会讲

Stack(栈):继承自Vector类,实现了一个后进先出(LIFO)的栈。CopyOnWriteArrayList:这是一个线程安全的列表,适用于读操作频繁、写操作较少的场景。AbstractList:这是一个抽象类,实现了List接口的大部分方法,可以作为其他列表实现的基类。ImmutableList:这是Guava库中提供的一个不可变列表的实现。AbstractSequentialList:这是一个抽象类,实现了List接口,并且以链接结构存储元素,适用于顺序访问元素的场景。

除了这些,还有许多其他的列表实现,有些是第三方库提供的,有些是Java平台的其他部分提供的。每种列表实现都有其自身的特点和适用场景。

List的特点 (不重要)

有序性(Ordering):List中的元素按照插入顺序排列,每个元素都有一个与之关联的索引。允许重复(Duplicates):List允许存储重复的元素,即同一个元素可以出现多次。可变性(Mutability):大多数List实现是可变的,即可以动态地增加、删除和修改其中的元素。索引访问(Indexed Access):可以通过索引来访问List中的元素,索引从0开始计数。Iterable接口(Iterable Interface):List实现了Iterable接口,因此可以使用增强型for循环和迭代器来遍历其中的元素。

如何创建List

以下是创建List的方法

import java.util.ArrayList;

import java.util.LinkedList;

import java.util.List;

import java.util.Stack;

import java.util.Vector;

public class Main {

public static void main(String[] args) {

List list_1 = new ArrayList();

List list_2 = new LinkedList();

List list_3 = new Vector();

List list_4 = new Stack();

}

}

那么你是否已经生出疑问?

List list_1 = new ArrayList();

ArrayList list_5 = new ArrayList();

这两句代码哪一种是你常写或者你常见的呢?

我要告诉你的是,这两句代码他们的效果是一样的,但为什么会有两种写法呢?如果你有意向深入,那么接下来的内容可以看看,你也可以选择先跳过

在语义上,这两句代码的效果是相同的,它们都创建了一个 ArrayList 类型的列表对象。

但是,在编程时,通常建议使用接口类型来声明变量,而不是具体的实现类。这样做有几个好处:

更好的封装:使用接口类型声明变量,可以将变量类型与实现类分离,从而提高代码的灵活性和可维护性。降低耦合度:接口类型的变量只关心方法的签名,而不关心具体的实现细节,因此可以轻松地切换不同的实现类而不影响其他部分的代码。符合面向接口编程的原则:面向接口编程是一种良好的编程实践,它能够提高代码的可复用性和可测试性。

因此,建议使用 List list_1 = new ArrayList(); 这种方式,以接口类型声明变量,从而获得更好的代码设计和可维护性。

List常用方法

add(E e):在列表末尾添加指定的元素。get(int index):返回列表中指定位置的元素。set(int index, E element):将列表中指定位置的元素替换为指定的元素。remove(int index):移除列表中指定位置的元素,并返回被移除的元素。size():返回列表中的元素数。isEmpty():判断列表是否为空。contains(Object o):判断列表是否包含指定的元素。indexOf(Object o):返回列表中指定元素第一次出现的索引。lastIndexOf(Object o):返回列表中指定元素最后一次出现的索引。subList(int fromIndex, int toIndex):返回列表中指定范围的部分视图。

import java.util.ArrayList;

public class Main {

public static void main(String[] args) {

List list_1 = new ArrayList();

list_1.add(1);list_1.add(2);list_1.add(3);list_1.add(4);

list_1.set(0, 2);

list_1.get(0);

list_1.remove(0);

list_1.size();

list_1.isEmpty();

list_1.contains(1);

list_1.indexOf(2);

list_1.lastIndexOf(2);

list_1.subList(1, 3);

}

}

当然,这些方法理论上对list的任意实现类都可以使用,但是它们并不包含输出效果,所以上面的代码没有任何输出。

值得一提的是,在上一篇Arrays类当中貌似忘记提了一点,就是list是可以直接使用System.out.println();语句输出的,和数组是不一样的。

import java.util.ArrayList;

public class Main {

public static void main(String[] args) {

List list_1 = new ArrayList();

list_1.add(1);list_1.add(2);list_1.add(3);list_1.add(4);

list_1.set(0, 2);

System.out.println(list_1.get(0));

list_1.remove(0);

System.out.println(list_1.size());

System.out.println(list_1.isEmpty());

System.out.println(list_1.contains(1));

System.out.println(list_1.indexOf(2));

System.out.println(list_1.lastIndexOf(2));

System.out.println(list_1.subList(1, 3));

}

}

我们只要将它改成这样就会得到输出

2

3

false

false

0

0

[3, 4]

区别

要知道既然list分为了这么多不同的实现类,那么,一定是有区别滴!

ArrayList&LinkedList

import java.util.ArrayList;

public class Main {

public static void main(String[] args) {

// 创建一个ArrayList

ArrayList arrayList = new ArrayList<>();

// 添加元素到ArrayList

arrayList.add("Apple");

arrayList.add("Banana");

arrayList.add("Orange");

// 遍历ArrayList

for (String fruit : arrayList) {

System.out.println(fruit);

}

}

}

import java.util.LinkedList;

public class Main {

public static void main(String[] args) {

// 创建一个LinkedList

LinkedList linkedList = new LinkedList<>();

// 添加元素到LinkedList的开头

linkedList.addFirst("Apple");

linkedList.addFirst("Banana");

linkedList.addFirst("Orange");

// 遍历LinkedList

for (String fruit : linkedList) {

System.out.println(fruit);

}

}

}

这两段代码看上去没有任何区别,但是 ArrayList支持随机访问

LinkedList 也支持随机访问,但是与 ArrayList 不同,LinkedList 的随机访问效率比较低,因为它需要从头或尾开始遍历链表,直到找到目标元素为止。这是因为 LinkedList 是通过链表实现的,每个节点只知道自己的前驱和后继节点,而不像 ArrayList 那样可以通过索引直接访问。

虽然 LinkedList 也支持随机访问,但是相对于 ArrayList 来说,它的性能会比较低,尤其是在大量随机访问操作时。因此,如果需要频繁进行随机访问操作,建议使用 ArrayList。

Vector

Vector 是 Java 中的一个传统集合类,它实现了动态数组的数据结构,与 ArrayList 类似。但是,Vector 是线程安全的,它的方法都是同步的,这意味着在多线程环境下,Vector 可以安全地被多个线程同时访问和修改。但是,这种同步机制也带来了性能上的一定损失。

以下是关于 Vector 类的一些重要点:

线程安全性:Vector 的所有方法都是同步的,可以安全地在多个线程之间共享。容量增长:与 ArrayList 类似,Vector 也具有自动扩容的功能,当容量不足时,会自动增加容量。遍历和访问:可以使用类似于 ArrayList 的方式来访问和遍历 Vector 中的元素。迭代器:Vector 提供了迭代器用于遍历元素。不推荐使用:由于其同步机制的性能损失以及更现代的 ArrayList 和 LinkedList 类的出现,一般不推荐使用 Vector。相比之下,ArrayList 在非多线程环境下通常具有更好的性能,而 LinkedList 则在插入和删除操作频繁的情况下可能更高效。 import java.util.Vector;

public class Main {

public static void main(String[] args) {

Vector vector = new Vector<>();

// 添加元素

vector.add(1);

vector.add(2);

vector.add(3);

// 获取元素

System.out.println("Element at index 1: " + vector.get(1));

// 遍历元素

System.out.print("Vector elements: ");

for (Integer num : vector) {

System.out.print(num + " ");

}

System.out.println();

}

}

在实际开发中,除非需要线程安全的集合类,否则一般建议使用 ArrayList 或 LinkedList 来替代 Vector。

Stack

Stack 是 Java 中的一个类,它是一种后进先出(LIFO)的数据结构,类似于现实生活中的堆栈,例如书桌上的书堆或者餐厅里的盘子堆。在 Stack 中,最后添加的元素将会被最先移除。

我记得之前看过一个非常详细的例子但是忘记出处了,如果有人知道可以提醒我

就是说栈是否给你一种像栈道一样长长的感觉,那么就很容易联想到桶装的薯片,生产的时候最先装进去的那一片,就是你最后吃到的一片。

以下是关于 Stack 类的一些重要点:

继承关系:Stack 类继承自 Vector 类,因此它包含了 Vector 类的所有方法,并在此基础上实现了堆栈的特性。后进先出:在 Stack 中,最后添加的元素将会被最先移除,这就是后进先出的特性。常用方法:Stack 提供了一些常用的方法,例如 push() 将元素推入栈顶,pop() 将栈顶元素移除并返回,peek() 获取栈顶元素但不移除等。空栈异常:在尝试对空栈执行 pop() 或 peek() 操作时,将会抛出 EmptyStackException 异常。应用场景:Stack 在许多场景中都有应用,例如表达式求值、括号匹配、深度优先搜索等算法中。

import java.util.Stack;

public class Main {

public static void main(String[] args) {

Stack stack = new Stack<>();

// 将元素推入栈顶

stack.push(1);

stack.push(2);

stack.push(3);

// 弹出栈顶元素

int topElement = stack.pop();

System.out.println("Top element popped: " + topElement);

// 获取栈顶元素但不移除

int peekElement = stack.peek();

System.out.println("Top element (peek): " + peekElement);

// 遍历栈元素

System.out.print("Stack elements: ");

while (!stack.isEmpty()) {

System.out.print(stack.pop() + " ");

}

System.out.println();

}

}

当然我们上面也提到过,Stack在java中属于是Vector的分支,那么我们也讲了Vector在内存上的损耗。在实际开发中,Stack 类在一些特定场景下非常有用,例如在处理算法中的栈相关问题时。但需要注意的是,由于 Stack 是线程安全的类,使用 Deque 的实现类 ArrayDeque 或 LinkedList 通常在性能上更好。

Deque(Double Ended Queue)在这里提一嘴,它也可以达成与栈一样的先进后出的效果。Deque 接口提供了一系列方法,可以从队列的两端添加、移除和检查元素。这使得 Deque 既可以作为队列使用,也可以作为栈使用,具有很高的灵活性。例如,addFirst() 和 removeFirst() 方法用于操作队列的头部,addLast() 和 removeLast() 方法用于操作队列的尾部。

import java.util.Deque;

import java.util.ArrayDeque;

public class Main {

public static void main(String[] args) {

// 创建一个双端队列

Deque deque = new ArrayDeque<>();

// 添加元素到队列尾部

deque.addLast(1);

deque.addLast(2);

deque.addLast(3);

// 遍历队列,输出队列元素(先进先出)

System.out.print("Queue (FIFO): ");

while (!deque.isEmpty()) {

System.out.print(deque.removeFirst() + " ");

}

System.out.println();

// 添加元素到栈顶

deque.addFirst(1);

deque.addFirst(2);

deque.addFirst(3);

// 遍历栈,输出栈元素(后进先出)

System.out.print("Stack (LIFO): ");

while (!deque.isEmpty()) {

System.out.print(deque.removeFirst() + " ");

}

System.out.println();

}

}

与Arrays类的联系

这里算是个伏笔,也就是为什么我在上一篇介绍了Arrays类的相关内容,正是因为Arrays类的一些操作方法对List也是适用的。嘿嘿。

Integer[] array = {1, 2, 3, 4, 5};

List list = Arrays.asList(array);

List list = new ArrayList<>();

// 添加元素到列表

list.add(1);

list.add(2);

list.add(3);

// 转换为数组

Integer[] array = list.toArray(new Integer[list.size()]);

String[] array = {"apple", "banana", "orange"};

String str = Arrays.toString(array); // 输出:[apple, banana, orange]

List list = Arrays.asList("apple", "banana", "orange");

int index = list.indexOf("banana"); // 返回 1

List list = new ArrayList<>();

list.addAll(Arrays.asList(1, 2, 3)); // 添加元素 1, 2, 3

List list = new ArrayList<>(Arrays.asList(5, 3, 1, 4, 2));

list.sort(Comparator.reverseOrder()); // 降序排序

List list = Arrays.asList("apple", "banana", "orange");

boolean contains = list.contains("banana"); // 返回 true

以上都是一些例子

小细节

不知道你有没有生出疑问,反正我有

ArrayList list = new ArrayList<>(); 你不好奇最后面那个小括号是拿来干嘛的吗?老弄我心痒痒

ArrayList 的括号 "()" 内部可以包含一些参数,这些参数通常用于构造函数。在这里,你可以指定初始容量或者从另一个 Collection 对象初始化 ArrayList。

// 指定初始容量为 20 的 ArrayList

ArrayList list = new ArrayList<>(20);

ArrayList anotherCollection = new ArrayList<>();

// 添加一些元素到 anotherCollection 中

// 从另一个 Collection 对象初始化 ArrayList

ArrayList list = new ArrayList<>(anotherCollection);

完结!!!

相关资讯

影驰GeForce GTX 960虎将
www365betcom手机版

影驰GeForce GTX 960虎将

⌚ 09-12 👁️ 987
幟結尾的成語:
beat365在线平台网址

幟結尾的成語:

⌚ 08-30 👁️ 7360