杰瑞科技汇

Java List类如何正确使用?

Of course! The java.util.List interface is one of the most fundamental and frequently used data structures in Java. Let's break it down comprehensively.

Java List类如何正确使用?-图1
(图片来源网络,侵删)

What is a List?

In Java, a List is an ordered collection (also known as a sequence). It allows you to store elements where the position (index) of each element is significant.

Here are the key characteristics of a List:

  1. Ordered: Elements are stored in a specific order, which is the order in which they were inserted. This order is preserved.
  2. Allows Duplicates: Unlike a Set, a List can contain duplicate elements.
  3. Indexed: Every element in a List has a zero-based index (get(0) gets the first element, get(1) gets the second, etc.). This allows for fast access to elements by their position.
  4. Dynamic Size: You can add or remove elements, and the List will grow or shrink accordingly.

The List Interface vs. ArrayList vs. LinkedList

This is a very common point of confusion for Java beginners. It's crucial to understand the difference.

Feature List (Interface) ArrayList (Class) LinkedList (Class)
Type An interface that defines a contract for a list. A concrete class that implements the List interface. A concrete class that implements the List interface.
Internal Structure N/A Uses a dynamic array to store elements. Uses a doubly-linked list of nodes.
Performance N/A Fast for random access (get(index)). Slow for insertions/deletions in the middle. Fast for insertions/deletions (if you have the node). Slow for random access.
Memory Usage N/A Generally more memory-efficient per element. Uses more memory as each element stores pointers to the next and previous nodes.
When to Use When you want to write code that is decoupled from the specific implementation. This is good practice. Default choice. Use when you need fast random access and don't have many insertions/deletions in the middle of the list. Use when you have a very large list and you frequently add/remove elements from the beginning or middle.

Analogy:

Java List类如何正确使用?-图2
(图片来源网络,侵删)
  • List is the blueprint for a "sequence of items."
  • ArrayList is like a dynamic array of boxes. It's great for grabbing any box instantly by its number, but inserting a new box in the middle requires shifting all the other boxes.
  • LinkedList is like a treasure hunt where each clue points to the next one. It's easy to add a new clue in the middle (just change the pointers on the surrounding clues), but finding the 100th clue means you have to follow the first 99 clues one by one.

How to Create a List

You almost always declare your list variable with the interface type (List) but instantiate it with a concrete class (ArrayList or LinkedList). This is a core principle of programming to the interface.

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
// 1. Using ArrayList (most common)
List<String> names = new ArrayList<>();
// 2. Using LinkedList
List<Integer> numbers = new LinkedList<>();
// You can also specify the initial capacity for an ArrayList (optional)
List<String> bigList = new ArrayList<>(100); // Pre-allocates space for 100 elements

Common Methods of the List Interface

Here are the most frequently used methods, with examples.

Adding Elements

List<String> fruits = new ArrayList<>();
fruits.add("Apple");      // Adds "Apple" to the end of the list. List: ["Apple"]
fruits.add("Banana");     // Adds "Banana" to the end. List: ["Apple", "Banana"]
fruits.add(0, "Orange");  // Adds "Orange" at index 0. List: ["Orange", "Apple", "Banana"]

Accessing Elements

List<String> fruits = new ArrayList<>(List.of("Orange", "Apple", "Banana"));
String firstFruit = fruits.get(0);      // Returns "Orange"
int size = fruits.size();               // Returns 3
boolean hasApple = fruits.contains("Apple"); // Returns true
int appleIndex = fruits.indexOf("Apple");    // Returns 1

Removing Elements

List<String> fruits = new ArrayList<>(List.of("Orange", "Apple", "Banana"));
fruits.remove("Apple");   // Removes the first occurrence of "Apple". List: ["Orange", "Banana"]
fruits.remove(0);         // Removes the element at index 0. List: ["Banana"]

Iterating (Looping Through) a List

There are several ways to do this.

Enhanced For-Loop (Most Common)

Java List类如何正确使用?-图3
(图片来源网络,侵删)
List<String> fruits = List.of("Apple", "Banana", "Cherry");
for (String fruit : fruits) {
    System.out.println(fruit);
}
// Output:
// Apple
// Banana
// Cherry

Using an Iterator The Iterator is the safest way to modify a list while iterating.

List<String> fruits = new ArrayList<>(List.of("Apple", "Banana", "Cherry"));
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
    String fruit = iterator.next();
    if ("Banana".equals(fruit)) {
        iterator.remove(); // Safely removes the current element
    }
}
System.out.println(fruits); // Output: [Apple, Cherry]

Using Java 8 Streams

List<String> fruits = List.of("Apple", "Banana", "Cherry");
fruits.stream()
      .forEach(fruit -> System.out.println(fruit.toUpperCase()));
// Output:
// APPLE
// BANANA
// CHERRY

Using an Index (Classic For-Loop) Use this if you need the index number.

for (int i = 0; i < fruits.size(); i++) {
    System.out.println("Fruit at index " + i + " is " + fruits.get(i));
}

Java 8 and Beyond: New Methods

Java 8 introduced several powerful methods that make working with collections much more concise.

forEach(Consumer<? super E> action)

Performs an action for each element of the list.

List<String> fruits = List.of("Apple", "Banana", "Cherry");
fruits.forEach(System.out::println); // Method reference, very clean!

removeIf(Predicate<? super E> filter)

Removes all elements of this list that satisfy the given predicate.

List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
numbers.removeIf(n -> n % 2 == 0); // Removes all even numbers
System.out.println(numbers); // Output: [1, 3, 5, 7, 9]

replaceAll(UnaryOperator<E> operator)

Replaces each element of this list with the result of applying the operator to that element.

List<String> names = new ArrayList<>(List.of("alice", "bob", "charlie"));
names.replaceAll(String::toUpperCase); // Method reference to toUpperCase()
System.out.println(names); // Output: [ALICE, BOB, CHARLIE]

sort(Comparator<? super E> c)

Sorts the list according to the order induced by the specified Comparator.

List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
names.sort(String::compareToIgnoreCase); // Sorts alphabetically, ignoring case
System.out.println(names); // Output: [Alice, Bob, Charlie]

Thread-Safety: CopyOnWriteArrayList

The standard ArrayList and LinkedList are not thread-safe. If multiple threads try to modify a list at the same time, it can lead to unpredictable behavior or corruption.

If you need a thread-safe list, you have a few options:

  1. Collections.synchronizedList(new ArrayList<>()): Wraps a list in a synchronized decorator. All methods are synchronized, but you must manually synchronize on the list when iterating.
  2. CopyOnWriteArrayList: A thread-safe variant of ArrayList. It's excellent for situations where you have far more reads than writes. When you modify the list, it creates a new copy of the underlying array. Iterators reflect the state of the list at the time they were created.
// A thread-safe list for concurrent reads
List<String> concurrentList = new java.util.concurrent.CopyOnWriteArrayList<>();

Summary: When to Use What

Your Need Best Choice Why?
Default choice, general purpose ArrayList Best all-around performance for most use cases.
Frequent additions/removals from the middle LinkedList Operations are much faster as they don't require shifting elements.
Need to iterate frequently ArrayList Iterating over an array is extremely fast.
Need thread safety CopyOnWriteArrayList (for many reads) or Collections.synchronizedList Provides safe concurrent access.
分享:
扫描分享到社交APP
上一篇
下一篇