//TestArrayListOperations.java
//Illustrates most of what are (probably) the most useful and
//frequently used ArrayList methods. As you experiment with this
//program, you should check the official ArrayList documentation
//and compare what you see there with what you see here.
//See TestArrayList_toArray.java for illustrations of toArray().

import java.util.ArrayList;
import java.util.Arrays;

public class TestArrayListOperations
{
    public static void main(String[] args)
    {
        //Illustrates the default constructor and methods add(value),
        //and size(), as well as indexOf(value) and lastIndexOf(value).
        //Creates a new (empty) ArrayList of Integer and displays its size.
        //Then adds some values and displays the size again.
        //Note that autoboxing happens as the values are added.
        //Then displays the first and last index locations of the value 2.
        //Finally, displays all of the values.
        System.out.println("=====1==============================");
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        System.out.println("Size = " + arrayList1.size());
        arrayList1.add(5);
        arrayList1.add(2);
        arrayList1.add(9);
        arrayList1.add(4);
        arrayList1.add(7);
        arrayList1.add(2);
        System.out.println("Size = " + arrayList1.size());
        System.out.println("First index of 2 = " + arrayList1.indexOf(2));
        System.out.println("Last index of 2 = " + arrayList1.lastIndexOf(2));
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();

        //Illustrates methods add(index, value), contains(value)
        //remove(index) and remove(value), removeIf(condition),
        //as well as how to remove a range of values, which involves
        //the use of subList(start, end).
        System.out.println("=====2==============================");
        System.out.println("Is 6 present? " + arrayList1.contains(6));
        arrayList1.add(3, 6);
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println("Is 6 present? " + arrayList1.contains(6));
        arrayList1.remove(5); //Note carefully. Compare with remove() below.
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        Integer iObj = 5;
        arrayList1.remove(iObj); //Note carefully. Compare with remove() above.
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        arrayList1.removeIf(i -> i % 2 == 1);
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        //arrayList1.removeRange(1, 3);
        //Somewhat surprisingly, the above line will not compile.
        //The reason is simple: it's a protected method. The reason
        //it's protected is a little more complicated and we do not
        //discuss it here. Google will fill you in ...
        //Here's the alternative:
        arrayList1.subList(1, 3).clear();
        for (int i : arrayList1)
        {
            System.out.print(i + " ");
        }
        System.out.println();

        //Illustrates ArrayList constructor that takes a container as input.
        //Uses the same values as for the first container.
        System.out.println("=====3==============================");
        ArrayList<Integer> arrayList2 =
            new ArrayList<>(Arrays.asList(5, 2, 9, 4, 7, 2));
        for (int i : arrayList2)
        {
            System.out.print(i + " ");
        }
        System.out.println();

        //Illustrate clear() and isEmpty().
        System.out.println("=====4==============================");
        arrayList2.clear();
        for (int i : arrayList2)
        {
            System.out.print(i + " ");
        }
        System.out.println("\nAbove line contains values after clear().");
        if (arrayList2.isEmpty())
        {
            System.out.println("The ArrayList is now empty.");
        }

        //Illustrate sort(), the default version as well as two
        //different lambda functions for determining how to sort.
        ArrayList<Integer> arrayList3 =
            new ArrayList<>(Arrays.asList(5, 2, 9, 4, 7, 2));
        arrayList3.sort(null); //Sorts using the "natural order"
        for (int i : arrayList3)
        {
            System.out.print(i + " ");
        }
        System.out.println();
        //The following two lines both sort in reverse,
        //but the second is the preferred option.
        arrayList3.sort((i1, i2) -> i2 - i1);
        arrayList3.sort((i1, i2) -> Integer.compare(i2, i1));
        for (int i : arrayList3)
        {
            System.out.print(i + " ");
        }
        System.out.println();
    }
}
/*  Output:
    =====1==============================
    Size = 0
    Size = 6
    First index of 2 = 1
    Last index of 2 = 5
    5 2 9 4 7 2
    =====2==============================
    Is 6 present? false
    5 2 9 6 4 7 2
    Is 6 present? true
    5 2 9 6 4 2
    2 9 6 4 2
    2 6 4 2
    2 2
    =====3==============================
    5 2 9 4 7 2
    =====4==============================

    Above line contains values after clear().
    The ArrayList is now empty.
    2 2 4 5 7 9
    9 7 5 4 2 2
*/

/*
    Just a note in passing ... below is another way to create
    an ArrayList (of strings), which would require these imports:
    import java.util.Collections;
    import java.util.stream.Stream;

    Stream.of("xyz", "abc").collect(Collectors.toList());
    You can ignore this approach for the time being.
*/
