List

A List promises to maintain elements in a specific sequence. The List interface adds a number of methods to the Collection, making it possible to insert and remove elements in the middle of the List.

There are two basic types of List:

  1. A basic ArrayList, which is longer than randomly accessing elements but slower to insert and remove elements from the middle of the List.
  2. LinkedList, which provides optimized sequential access through inexpensive insert and delete operations in the middle of a List. LinkedList is slower for random access, but it has a larger feature set than ArrayList.
ArrayList
package p10;

import java.util.*;

public class ListFeatures {
    public static void main(String[] args) {
        Random random = new Random(47);
        List<Pet> petList = Pets.arrayList(7);
        System.out.println("1." + petList);
        Hamster h = new Hamster();
        petList.add(h); // Automatically resizes
        System.out.println("2." + petList);
        System.out.println("3." + petList.contains(h));
        petList.remove(h);
        Pet p = petList.get(2);
        System.out.println("4." + p + "" + petList.indexOf(p));
        Pet cymric = new Cymric();
        System.out.println("5." + petList.indexOf(cymric));
        System.out.println("6." + petList.remove(cymric));
        // Must be the exact object
        System.out.println("Seven." + petList.remove(p));
        System.out.println("8." + petList);
        petList.add(3.new Mouse());
        System.out.println("Nine." + petList);
        List<Pet> sub = petList.subList(1.4);
        System.out.println("subList: " + sub);
        System.out.println("10: " + petList.containsAll(sub));
        Collections.sort(sub); // In-place sort
        System.out.println("sorted subList: " + sub);
        // Order is not important in containsAll
        System.out.println("11." + petList.containsAll(sub));
        Collections.shuffle(sub,random);
        System.out.println("shuffled subList: " + sub);
        System.out.println("12." + petList.containsAll(sub));
        List<Pet> copy = new ArrayList<>(petList);
        sub = Arrays.asList(petList.get(1),petList.get(4));
        System.out.println("sub: " + sub);
        copy.retainAll(sub);
        System.out.println("13." + copy);
        copy = new ArrayList<>(petList);
        copy.remove(2);
        System.out.println("14." + copy);
        copy.removeAll(sub);
        System.out.println("15." + copy);
        copy.set(1.new Mouse());
        System.out.println("16." + copy);
        copy.addAll(2,sub);
        System.out.println("Seventeen." + copy);
        System.out.println("18." + petList.isEmpty());
        petList.clear(); // Remove all elements
        System.out.println("19." + petList);
        System.out.println("20." + petList.isEmpty());
        petList.addAll(Pets.arrayList(4));
        System.out.println("21." + petList);;
        Object[] o = petList.toArray();
        System.out.println("22." + o[3]);
        Pet[] pa = petList.toArray(new Pet[0]);
        System.out.println("23." + pa[3].id());
    }
    /** * 1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug] * 2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster] * 3: true * 4: Cymric 2 * 5: -1 * 6: false * 7: true * 8: [Rat, Manx, Mutt, Pug, Cymric, Pug] * 9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug] * subList: [Manx, Mutt, Mouse] * 10: true * sorted subList: [Manx, Mouse, Mutt] * 11: true * shuffled subList: [Mouse, Manx, Mutt] * 12: true * sub: [Mouse, Pug] * 13: [Mouse, Pug] * 14: [Rat, Mouse, Mutt, Pug, Cymric, Pug] * 15: [Rat, Mutt, Cymric, Pug] * 16: [Rat, Mouse, Cymric, Pug] * 17: [Rat, Mouse, Mouse, Pug, Cymric, Pug] * 18: false * 19: [] * 20: true * 21: [Manx, Cymric, Rat, EgyptianMau] * 22: EgyptianMau * 23: 14 */
}
Copy the code

You can use the contains() method to determine if an object is in the list. If you want to remove an object, you can pass a reference to the object to the remove() method. Similarly, if you have a reference to an object, you can use indexOf() to find the index number of that object’s position in the List, as you can see in line 4 of output.

The equals() method (which is part of the root Object class) is used when determining whether an element belongs to a List, discovering an element’s index, and removing an element from a List. Each Pet is defined as a unique object, so even though I already have two Cymric in the list, if I create a new Cymric and pass it to indexOf(), the result will still be -1(indicating that it was not found) and try to remove the object by calling remove(), Also returns false. For other classes, equals() may be defined differently. For example, two strings are equivalent only if their contents are exactly the same. So to prevent surprises, it’s important to realize that the behavior of the List varies depending on the behavior of equals().

In output lines 7 and 8, it is shown that removing an object that exactly matches an object in the List is successful. It is possible to insert elements in the middle of the List, as you can see in line 9 of output and the code before it. But this poses a problem: For linkedLists, inserting and deleting in the middle of the list are cheap operations (in this case, except for a truly random access to the middle of the list), but for arrayLists, they are costly. Does that mean you should never insert elements in the middle of an ArrayList, and would be better off switching to a LinkedList? No, it just means that you should be aware of the problem, and if you start doing a lot of inserts in the middle of an ArrayList, and your program starts to slow down, you should look at your List implementation and see if it might be the culprit. Optimization is a tricky problem, and the best strategy is to ignore it until you know you need to worry about it (although it’s always a good idea to understand these issues). The subList() method allows you to easily create a fragment from a larger list, and passing the result to the containsAllO method of the larger list naturally returns true. It’s also interesting to note that the order doesn’t matter, as you can see in output lines 11 and 12 that calling the intuitively named collections.sort () and collection.shuffle () methods on sub doesn’t affect the result of containsAll(). Behind the list produced by subList() is the original list, so changes to the returned list are reflected in the original list and vice versa. The retainAll() method is a valid “intersection” operation, which in this case preserves all elements in both copy and sub. Note again that the resulting behavior depends on the equals0 method.

The naming of the set() method is awkward because of a potential conflict with the set class. Here, replace might be more appropriate, because its function is to replace elements in the entire position with the second argument at the specified index (the first argument).

Line 17 of output shows that for the List, there is an overloaded addAll() method that allows us to insert a new List in the middle of the original List, rather than just append it to the end with the addAll() method in the Collection. Lines 18-20 of output show the effect of the isEmpty() and clear() methods.

Output lines 22-23 show how you can convert any Collection to an array using the toArray() method. This is an overloaded method whose no-argument version returns an Object array, but if you pass the target type of data to this overloaded version, it will produce data of the specified type (assuming it passes the type check). If the array is too small to hold all the elements in the List (as in this example), the toArray() method creates an array of the appropriate size. Pet objects have an ID () method that, as you can see, can be called on objects in the resulting array.

package p10;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for(int i = 10; i >=0; i--){ list.add(i); } List<Integer> subList = list.subList(1.5);
        Collections.sort(subList);
        System.out.println(subList);
        System.out.println(list);
        / * * * * [6, 7, 8, 9] [10, 6, 7, 8, 9, 5, 4, 3, 2, 1, 0] * /}}Copy the code
LinkedList

LinkedList also implements the basic List interface like ArrayList, but it performs some operations (inserting and removing from the middle of a List) more efficiently than ArrayList, but is less effective at random access operations.

LinkedList also adds methods that can be used as a stack, queue, or double-ended queue.

Some of these methods have only names that differ from each other, or only slightly, to make the names more appropriate in the context of a particular usage (especially in Queue). For example, getFirst() and Element () are exactly the same in that they both return the head of the List (the first element) without removing it, and throw nosuchElement-exception if the List is empty. The peek() method differs only slightly from these methods in that it returns NULL if the list is empty.

RemoveFirst () and remove() are exactly the same in that they remove and return the head of the list and throw a NoSuchElementException if the list is empty. Poll () is slightly different in that it returns NULL if the list is empty.

AddFirst () is the same as add() and addLast(), both of which insert an element at the end of the list. RemoveLast () removes and returns the last element of the list.

package p10;

import java.util.LinkedList;

public class LinkedListFeatures {
    public static void main(String[] args) {
        LinkedList<Pet> pets = new LinkedList<>(Pets.arrayList(5));
        System.out.println(pets);
        // Identical
        System.out.println("pets.getFirst(): " + pets.getFirst());
        System.out.println("pets.element(): " + pets.element());
        // Only differs in empty-list behavior
        System.out.println("pets.peek(): " + pets.peek());

        // Identical: remove and return the first element
        System.out.println("pets.remove(): " + pets.remove());
        System.out.println("pets.removeFirst(): " + pets.removeFirst());
        // Only differs in empty-list behavior
        System.out.println("pets.poll() " + pets.poll());
        System.out.println(pets);
        pets.addFirst(new Rat());
        System.out.println("After addFirst(): " + pets);
        pets.offer(Pets.randomPet());
        System.out.println("After offer(): " + pets);
        pets.add(Pets.randomPet());
        System.out.println("After add(): " + pets);
        pets.addLast(new Hamster());
        System.out.println("After addLast(): " + pets);
        System.out.println("pets.removeLast(): " + pets.removeLast());
        /** * [Rat, Manx, Cymric, Mutt, Pug] * pets.getFirst(): Rat * pets.element(): Rat * pets.peek(): Rat * pets.remove(): Rat * pets.removeFirst(): Manx * pets.poll() Cymric * [Mutt, Pug] * After addFirst(): [Rat, Mutt, Pug] * After offer(): [Rat, Mutt, Pug, Cymric] * After add(): [Rat, Mutt, Pug, Cymric, Pug] * After addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster] * pets.removeLast(): Hamster */}}Copy the code