Sunday, November 14, 2021

Java Tutorial: Collections Class

Chapters

Collections Class

Collections class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

The methods of this class all throw a NullPointerException if the collections or class objects provided to them are null. This class is a member of the Java Collections Framework.

In this tutorial, I'm gonna demonstrate some methods of this class. More information can be found in the documentation.

addAll() Method

This method adds all of the specified elements to the specified collection. Elements to be added may be specified individually or as an array. Returns true if the specified collection has changed due to this method call. Otherwise, returns false.
Method form: addAll(Collection<? super T> c, T... elements)
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    System.out.println("Add individual elements...");
    Collections.addAll(ar, "Avocado","Orange","Mango");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
    
    System.out.println("Add array...");
    String[] arr1 = {"Mangosteen","Guava"};
    
    Collections.addAll(ar, arr1);
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
  }
}

Result
Add individual elements...
Elements...
Avocado
Orange
Mango
Add array...
Elements...
Avocado
Orange
Mango
Mangosteen
Guava

asLifoQueue() Method

Returns a view of a Deque as a Last-in-first-out (Lifo) Queue. Method add is mapped to push, remove is mapped to pop and so on. This view can be useful when you would like to use a method requiring a Queue but you need Lifo ordering.

Each method invocation on the queue returned by this method results in exactly one method invocation on the backing deque, with one exception. The addAll method is implemented as a sequence of addFirst invocations on the backing deque.
Method form: asLifoQueue(Deque<T> deque)
import java.util.Collections;
import java.util.ArrayDeque;
import java.util.Queue;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayDeque<String> ar =
    new ArrayDeque<>();
    
    System.out.println("Add elements to ArrayDeque...");
    ar.add("Cat");
    ar.add("Dog");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
      
    System.out.println("Create an ArrayDeque view "+
                       "as LIFO Queue...");
    Queue<String> lifo =
    Collections.asLifoQueue(ar);
    
    System.out.println("Add element using LIFO Queue...");
    lifo.add("Ocelot");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
    
    System.out.println("Reference ArrayDeque to a "+
                       "Queue Reference...");
                       
    Queue<String> queue = ar;
    System.out.println("Add element...");
    queue.add("Crocodile");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
  }
}

Result
Add elements to ArrayDeque...
Elements...
Cat
Dog
Create an ArrayDeque view as LIFO Queue...
Add element using LIFO Queue...
Elements...
Ocelot
Cat
Dog
Reference ArrayDeque to a Queue Reference...
Add element...
Elements...
Ocelot
Cat
Dog
Crocodile
binarySearch() Method

Searches the specified list for the specified object using the binary search algorithm. The list must be sorted into ascending order according to the natural ordering of its elements (as by the sort(List) method) prior to making this call. If it is not sorted, the results are undefined. If the list contains multiple elements equal to the specified object, there is no guarantee which one will be found.

This method runs in log(n) time for a "random access" list (which provides near-constant-time positional access). If the specified list does not implement the RandomAccess interface and is large, this method will do an iterator-based binary search that performs O(n) link traversals and O(log n) element comparisons.
This method has two forms. In this topic, I'm gonna demonstrate this form:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
The first parameter is the sorted list and the second parameter is the element that we wanna find.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<Byte> bytes =
    new ArrayList<gt;();
    
    Collections.addAll(bytes, new Byte[]{10, 50, 33, 11});
    
    byte target = 33;
    
    Collections.sort(bytes);
    
    int index = Collections.binarySearch(bytes, target);
    
    System.out.println("33 is at index: " + index);
  }
}

Result
33 is at index: 2

checked...() Methods

Methods like checkedList(), checkedSet(), checkedMap() and others return a dynamically typesafe view of a collection. For example, checkedList() returns a dynamic typesafe view of a List and checkedSet() returns a dynamic typesafe view of a Set.

Any attempt to insert an element of the wrong type will result in an immediate ClassCastException. Assuming a collection contains no incorrectly typed elements prior to the time a dynamically typesafe view is generated, and that all subsequent access to the list takes place through the view, it is guaranteed that the collection cannot contain an incorrectly typed element.

We can use these methods to create a typesafe view of a raw type collection. In modern java applications, raw types are rare. However, in old java applications raw types are often used. Raw type collections don't have type safety feature whereas generic collections have type safety feature.

In this topic, I'm gonna demonstrate the checkedList() method.
Method form: checkedList(List<E> list, Class<E> type)
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList bytes =
    new ArrayList();
    
    Collections.addAll(bytes, new Byte[]{10, 50, 33, 11});
    
    List<Byte> list = Collections.checkedList(bytes, Byte.class);
    
    //This statement should throw an exception but won't
    bytes.add("String");
    
    //This statement will throw a compile-time error
    //list.add("String");
    
    System.out.println("Elements...");
    for(Byte b : list)
      System.out.println(b);
  }
}

Result
Elements...
10
50
33
11
Exception in thread "main" java.lang.ClassCastException...
copy() Method

Copies all of the elements from one list into another. After the operation, the index of each copied element in the destination list will be identical to its index in the source list. The destination list's size must be greater than or equal to the source list's size.

If it is greater, the remaining elements in the destination list are unaffected. This method runs in O(n) linear time.
Method form: public static <T> void copy(List? <super T> dest, List<? extends T> src)

This example demonstrates copy() method.
import java.util.Collections;
import java.util.ArrayList;
import java.util.Vector;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>(3);
    
    ar.add("Horse");
    ar.add("Penguin");
    ar.add("Seahorse");
    
    Vector<String> vc =
    new Vector<>(3);
    
    vc.add("Shoes");
    vc.add("Belt");
    vc.add("Scissors");
    
    System.out.println("Vector elements...");
    for(String str : vc)
      System.out.println(str);
    
    System.out.println("Replace vector elements"+
    " with ArrayList elements...");
    //copy arraylist elements to
    //a list
    Collections.copy(vc, ar);
    
    System.out.println("Vector elements...");
    for(String str : vc)
      System.out.println(str);
    
  }
}

Result
Vector elements...
Shoes
Belt
Scissors
Replace vector elements with ArrayList elements...
Vector elements...
Horse
Penguin
Seahorse
disjoint() Method

Returns true if the two specified collections have no elements in common.

Care must be exercised if this method is used on collections that do not comply with the general contract for Collection. Implementations may elect to iterate over either collection and test for containment in the other collection (or to perform any equivalent computation).

If either collection uses a nonstandard equality test (as does a SortedSet whose ordering is not compatible with equals, or the key set of an IdentityHashMap), both collections must use the same nonstandard equality test, or the result of this method is undefined.

Care must also be exercised when using collections that have restrictions on the elements that they may contain. Collection implementations are allowed to throw exceptions for any operation involving elements they deem ineligible. For absolute safety the specified collections should contain only elements which are eligible elements for both collections.

Note that it is permissible to pass the same collection in both parameters, in which case the method will return true if and only if the collection is empty.
Method form: public static boolean disjoint(Collection<?> c1, Collection<?> c2)

This example demonsrates disjoint() method.
import java.util.Collections;
import java.util.ArrayList;
import java.util.LinkedList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    
    LinkedList<String> ll =
    new LinkedList<>();
    
    ll.add("Apple Pie");
    ll.add("Banana Cream");
    ll.add("Chopped Carrot");
    
    boolean result = Collections.disjoint(ar, ll);
    System.out.println(result);
  }
}

Result
true
empty...() Methods

Methods like emptyList(), emptySet() and emptyMap() return an empty and immutable collection. Immutable collection is a collection where its elements can't be changed once it's in the collection. Some of the methods that are similar to the methods that I mentioned earlier don't return an immutable collection. Methods like emptyEnumeration() and emptyIterator() don't return immutable collection.

In this topic, I'm gonna demonstrate the emptyList() method.
Method form: public static final <T> List<T> emptyList()

This example demonstrates emptyList().
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

public class SampleClass{

  public static void main(String[] args){
    
    List<String> list =
    Collections.emptyList();
    
    //UnsupportedOperationException
    //list.add("Banana");
    
  }
}
fill() Method

Replaces all of the elements of the specified list with the specified element. This method runs in linear time.
Method form: public static <T> void fill(List<? super T> list, T obj)

This example demonstrate fill() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
    
    Collections.fill(ar, "Fruits");
    
    System.out.println("New elements...");
    for(String str : ar)
      System.out.println(str);
    
  }
}

Result
Elements...
Apple
Banana
Carrot
New elements...
Fruits
Fruits
Fruits
frequency() Method

Returns the number of elements in the specified collection equal to the specified object. More formally, returns the number of elements e in the collection such that Objects.equals(o, e).
Method form: public static int frequency(Collection<?> c, Object o)
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    ar.add("Apple");
    
    int freq = Collections.frequency(ar, "Apple");
    
    System.out.println("# of \"Apple\": " + freq);
  }
}

Result
# of "Apple": 2
indexOfSubList() Method

Returns the starting position of the first occurrence of the specified target list within the specified source list, or -1 if there is no such occurrence. More formally, returns the lowest index i such that source.subList(i, i+target.size()).equals(target), or -1 if there is no such index. (Returns -1 if target.size() > source.size())

This implementation uses the "brute force" technique of scanning over the source list, looking for a match with the target at each location in turn.
Method form: public static int indexOfSubList(List<?> source, List<?> target)

This example demonsrates indexOfSubList() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar1 =
    new ArrayList<>();
    
    ar1.add("Apple");
    ar1.add("Banana");
    ar1.add("Apple");
    ar1.add("Carrot");
    ar1.add("Apple");
    ar1.add("Carrot");
    
    ArrayList<String> ar2 =
    new ArrayList<>();
    
    ar2.add("Apple");
    ar2.add("Carrot");
    
    int startIndex = 
    Collections.indexOfSubList(ar1,ar2);
    
    System.out.println("Start index of first occurence\n"
                       +"of sublist: " + startIndex);
  }
}

Result
Start index of first occurence
of sublist: 2
lastIndexOfSubList() Method

Returns the starting position of the last occurrence of the specified target list within the specified source list, or -1 if there is no such occurrence. More formally, returns the highest index i such that source.subList(i, i+target.size()).equals(target), or -1 if there is no such index. (Returns -1 if target.size() > source.size())

This implementation uses the "brute force" technique of iterating over the source list, looking for a match with the target at each location in turn.
Method form: public static int lastIndexOfSubList(List<?> source, List<?> target)

This example demonsrates lastIndexOfSubList() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar1 =
    new ArrayList<>();
    
    ar1.add("Apple");
    ar1.add("Banana");
    ar1.add("Apple");
    ar1.add("Carrot");
    ar1.add("Apple");
    ar1.add("Carrot");
    
    ArrayList<String> ar2 =
    new ArrayList<>();
    
    ar2.add("Apple");
    ar2.add("Carrot");
    
    int lastIndex = 
    Collections.lastIndexOfSubList(ar1,ar2);
    
    System.out.println("Start index of last occurence\n"
                       +"of sublist: " + lastIndex);
  }
}

Result
Start index of last occurence
of sublist: 4
max() Method

Returns the maximum element of the given collection, according to the natural ordering of its elements. All elements in the collection must implement the Comparable interface. Furthermore, all elements in the collection must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the collection).

This method iterates over the entire collection, hence it requires time proportional to the size of the collection. This method has two forms. In this tutorial, I'm gonna demonstrate this form:
Method form: public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

This example demonstrates max() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    ar.add("Apple");
    
    String maxElem = Collections.max(ar);
    
    System.out.println("Highest Element: " + maxElem);
  }
}

Result
Highest element: Carrot
min() Method

Returns the minimum element of the given collection, according to the natural ordering of its elements. All elements in the collection must implement the Comparable interface. Furthermore, all elements in the collection must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the collection).

This method iterates over the entire collection, hence it requires time proportional to the size of the collection. This method has two forms. In this tutorial, I'm gonna demonstrate this form:
Method form: public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)

This example demonstrates min() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    ar.add("Apple");
    
    String minElem = Collections.min(ar);
    
    System.out.println("Least Element: " + minElem);
  }
}

Result
Least element: Apple
nCopies() Method

Returns an immutable list consisting of n copies of the specified object. The newly allocated data object is tiny (it contains a single reference to the data object). This method is useful in combination with the List.addAll method to grow lists. The returned list is serializable.

Method form: public static <T> List<T> nCopies(int n, T o)
import java.util.Collections;
import java.util.List;

public class SampleClass{

  public static void main(String[] args){
    
    List<String> list =
    Collections.nCopies(4, "copyCat");
    
    for(String str : list)
      System.out.println(str);
  }
}

Result
copyCat
copyCat
copyCat
copyCat
newSetFromMap() Method

Returns a set backed by the specified map. The resulting set displays the same ordering, concurrency, and performance characteristics as the backing map. In essence, this factory method provides a Set implementation corresponding to any Map implementation. There is no need to use this method on a Map implementation that already has a corresponding Set implementation (such as HashMap or TreeMap)

Each method invocation on the set returned by this method results in exactly one method invocation on the backing map or its keySet view, with one exception. The addAll method is implemented as a sequence of put invocations on the backing map.

The specified map must be empty at the time this method is invoked, and should not be accessed directly after this method returns. These conditions are ensured if the map is created empty, passed directly to this method, and no reference to the map is retained, as illustrated in the following code fragment:
Set<Object> weakHashSet =
Collections.newSetFromMap(
new WeakHashMap<Object, Boolean>());
Method form: public static <E> Set<E> newSetFromMap(Map<E,Boolean> map)
This example demonstrates newSetFromMap() method.
import java.util.Collections;
import java.util.WeakHashMap;
import java.util.Set;

public class SampleClass{

  public static void main(String[] args){
   
   Set<Integer> weakHashSet =
   Collections.newSetFromMap(
   new WeakHashMap<Integer,Boolean>());
   
   weakHashSet.add(10);
   weakHashSet.add(25);
   weakHashSet.add(50);
   weakHashSet.add(125);
   
   for(Integer i : weakHashSet)
     System.out.println(i);
  }
}

Result
125
10
25
50
replaceAll() Method

This method replaces all occurrences of one specified value in a list with another.
Method form: public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)

This method demonstrates replaceAll() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    ar.add("Apple");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
      
    System.out.println("Replace Apple with Orange...");
    Collections.replaceAll(ar, "Apple", "Orange");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
  }
}

Result
Elements...
Apple
Banana
Carrot
Apple
Replace Apple with Orange...
Elements...
Orange
Banana
Carrot
Orange
reverse() Method

Reverses the order of the elements in the specified list. This method runs in linear time.
Method form: public static void reverse(List<?> list)

This method demonstrates reverse() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    ar.add("Mango");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
      
    System.out.println("Reverse elements...");
    Collections.reverse(ar);
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
  }
}

Result
Elements...
Apple
Banana
Carrot
Mango
Reverse elements...
Elements...
Mango
Carrot
Banana
Apple
reverseOrder() Method

This method returns a comparator that has a reverse ordering of an order. reverseOrder() Returns a comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface. (The natural ordering is the ordering imposed by the objects' own compareTo method).

reverseOrder(Comparator<T> cmp) Returns a comparator that imposes the reverse ordering of the specified comparator. If the specified comparator is null, this method is equivalent to reverseOrder() (in other words, it returns a comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface).

This example demonstrates reverseOrder() method.
import java.util.Collections;
import java.util.ArrayList;
import java.util.Comparator;

public class SampleClass{

  public static void main(String[] args){
    
    Comparator<String> comp =
    Collections.reverseOrder();
    
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    
    Collections.sort(ar, comp);
    System.out.println("ArrayList elements...");
    for(String str : ar)
      System.out.println(str);
    
  }
}

Result
ArrayList elements...
Carrot
Banana
Apple
rotate() Method

This method rotates elements around a collection. Positive distance moves elements to the right. Negative distance moves elements to the left. distance can be negative, positive or greater than the size of the collection.

Method form: public static void rotate(List<?> list, int distance)

This example demonsrates rotate() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<Integer> ar =
    new ArrayList<>();
    
    ar.add(1);
    ar.add(2);
    ar.add(3);
    ar.add(4);
    ar.add(5);
    
    System.out.println("Elements...");
    for(Integer i : ar)
      System.out.print(i + " ");
      
    Collections.rotate(ar, 3);
    
    System.out.println();
    System.out.println("Rotated elements...");
    for(Integer i : ar)
      System.out.print(i + " ");
  }
}
Elements...
1 2 3 4 5
Rotated elements...
3 4 5 1 2
In the example above, we have a positive distance which is 3. It means, each element in the collection will move to the right by 3 steps. For example:
Elements
{1, 2, 3, 4, 5}
Distance: 3

Move element at index 0 to the right by 3
{-, -, -, 1, -}
Move element at index 1 to the right by 3
{-, -, -, 1, 2}
Move element at index 2 to the right by 3
{3, -, -, 1, 2}
Move element at index 3 to the right by 3
{3, 4, -, 1, 2}
Move element at index 4 to the right by 3
{3, 4, 5, 1, 2}
Now, let's try a negative distance.
Elements
{1, 2, 3, 4, 5}
Distance: -3

Move element at index 0 to the left by 3
{-, -, 1, -, -}
Move element at index 1 to the left by 3
{-, -, 1, 2, -}
Move element at index 2 to the left by 3
{-, -, 1, 2, 3}
Move element at index 3 to the left by 3
{4, -, 1, 2, 3}
Move element at index 4 to the left by 3
{4, 5, 1, 2, 3}
Now, let's try a distance greater than the collection's size.
Elements
{1, 2, 3, 4, 5}
Distance: 6

Move element at index 0 to the right by 6
{-, 1, -, -, -}
Move element at index 1 to the right by 6
{-, 1, 2, -, -}
Move element at index 2 to the right by 6
{-, 1, 2, 3, -}
Move element at index 3 to the right by 6
{-, 1, 2, 3, 4}
Move element at index 4 to the right by 6
{5, 1, 2, 3, 4}
We can compute the the destination index of an element after rotation. Formula:
(i + distance) % size
Where:
i = index
size = collection's size
Now, let's try using the formula in the examples above
Elements
{1, 2, 3, 4, 5}
Distance: 3

Move element at index 0 to the right by 3
Compute: 
(0 + 3) % 5
3 % 5 = 3
destination index = 3
{-, -, -, 1, -}
Move element at index 1 to the right by 3
Compute: 
(1 + 3) % 5
4 % 5 = 4
destination index = 4
{-, -, -, 1, 2}
Move element at index 2 to the right by 3
Compute: 
(2 + 3) % 5
5 % 5 = 0
destination index = 0
{3, -, -, 1, 2}
Move element at index 3 to the right by 3
Compute: 
(3 + 3) % 5
6 % 5 = 1
destination index = 1
{3, 4, -, 1, 2}
Move element at index 4 to the right by 3
Compute: 
(4 + 3) % 5
7 % 5 = 2
destination index = 2
{3, 4, 5, 1, 2}
Now, let's try negative distance.
Elements
{1, 2, 3, 4, 5}
Distance: -3

Move element at index 0 to the left by 3
Compute: 
(0 + (-3)) % 5
-3 % 5 = -3
destination index = -3
{-, -, 1, -, -}
Move element at index 1 to the left by 3
Compute: 
(1 + (-3)) % 5
-2 % 5 = -2
destination index = -2
{-, -, 1, 2, -}
Move element at index 2 to the left by 3
Compute: 
(2 + (-3)) % 5
-1 % 5 = -1
destination index = -1
{-, -, 1, 2, 3}
Move element at index 3 to the left by 3
Compute: 
(3 + (-3)) % 5
0 % 5 = 0
destination index = 0
{4, -, 1, 2, 3}
Move element at index 4 to the left by 3
Compute: 
(4 + (-3)) % 5
1 % 5 = 1
destination index = 1
{4, 5, 1, 2, 3}
Remember, arrays can't have negative indexes. The negative indexes that we got from the computation denote indexes starting from right to left. For example:
Elements: {1, 2, 3, 4, 5}
index(+):  0  1  2  3  4
index(-):  0 -4 -3 -2 -1

So, the index -3 that we got from the computation above is equal to index 2. Now, let's try a distance that is greater than the size of the collection.
Elements
{1, 2, 3, 4, 5}
Distance: 6

Move element at index 0 to the right by 6
Compute: 
(0 + 6) % 5
6 % 5 = 1
destination index = 1
{-, 1, -, -, -}
Move element at index 1 to the right by 6
(1 + 6) % 5
7 % 5 = 2
destination index = 2
{-, 1, 2, -, -}
Move element at index 2 to the right by 6
(2 + 6) % 5
8 % 5 = 3
destination index = 3
{-, 1, 2, 3, -}
Move element at index 3 to the right by 6
(3 + 6) % 5
9 % 5 = 4
destination index = 4
{-, 1, 2, 3, 4}
Move element at index 4 to the right by 6
(4 + 6) % 5
10 % 5 = 0
destination index = 0
{5, 1, 2, 3, 4}
shuffle() Method

This method has two forms. In this topic, I'm gonna explain this form:
public static void shuffle(List<?> list)

shuffle() method randomly permutes the specified list using a default source of randomness. All permutations occur with approximately equal likelihood.

The hedge "approximately" is used in the foregoing description because default source of randomness is only approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen bits, then the algorithm would choose permutations with perfect uniformity.

This implementation traverses the list backwards, from the last element up to the second, repeatedly swapping a randomly selected element into the "current position". Elements are randomly selected from the portion of the list that runs from the first element to the current position, inclusive.

This method runs in linear time. If the specified list does not implement the RandomAccess interface and is large, this implementation dumps the specified list into an array before shuffling it, and dumps the shuffled array back into the list. This avoids the quadratic behavior that would result from shuffling a "sequential access" list in place.

This example demonstrates shuffle() method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
    
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Apple");
    ar.add("Banana");
    ar.add("Carrot");
    
    Collections.shuffle(ar);
    System.out.println("Shuffled elements...");
    for(String str : ar)
      System.out.println(str);
    
  }
}
singleton() Method

singleton(), singletonList() and singletonMap() return an immutable collection containing only the specified object. In this topic, I'm gonna demonstrate singleton() method. singleton() method returns an immutable list containing only the specified object.
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class SampleClass{

  public static void main(String[] args){
  
    Set<String> obj =
    Collections.singleton("Apple");
    
    HashSet<String> hs =
    new HashSet<>();
    
    hs.add("Apple");
    hs.add("Banana");
    hs.add("Carrot");
    
    System.out.println("Elements...");
    for(String str : hs)
      System.out.println(str);
      
    System.out.println("Remove Apple");
    hs.removeAll(obj);
    
    System.out.println("Elements...");
    for(String str : hs)
      System.out.println(str);
  }
}

Result
Elements...
Apple
Carrot
Banana
Remove Apple
Elements...
Carrot
Banana
sort() Method

This method has two forms. In this topic, I'm gonna explain this form:
Method form: public static <T extends Comparable<? super T>> void sort(List<T> list)

This method sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface. Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list).

This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort. The specified list must be modifiable, but need not be resizable.

This method demonstrates sort(List<T> list) method.
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
    
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Carrot");
    ar.add("Orange");
    ar.add("Apple");
    
    Collections.sort(ar);
    System.out.println("Sorted elements...");
    for(String str : ar)
      System.out.println(str);
    
  }
}

Result
Sorted elements...
Apple
Carrot
Orange
swap() Method

Swaps the elements at the specified positions in the specified list. (If the specified positions are equal, invoking this method leaves the list unchanged.)
Method form: public static void swap(List<?> list, int i, int j)
import java.util.Collections;
import java.util.ArrayList;

public class SampleClass{

  public static void main(String[] args){
  
    ArrayList<String> ar =
    new ArrayList<>();
    
    ar.add("Carrot");
    ar.add("Orange");
    ar.add("Apple");
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
      
    System.out.println("Swap Carrot to Apple");
    Collections.swap(ar, 0, 2);
    
    System.out.println("Elements...");
    for(String str : ar)
      System.out.println(str);
  }
}

Result
Elements...
Carrot
Orange
Apple
Swap Carrot to Apple
Elements...
Apple
Orange
Carrot
synchronized...() Methods

Methods like synchronizedList(), synchronizedSet() and synchronizedMap() return a synchronized(thread-safe) collection backed by the specified collection. In this topic, I'm gonna explain synchronizedList()
Method form: public static <T> List<T> synchronizedList(List<T> list)

This method returns a synchronized (thread-safe) list backed by the specified list. In order to guarantee serial access, it is critical that all access to the backing list is accomplished through the returned list.

It is imperative that the user manually synchronize on the returned list when traversing it. Failure to follow this advice may result in non-deterministic behavior. The returned list will be serializable if the specified list is serializable.

This example demonstrates synchronizedList(List<T> list) method.
import java.util.Collections;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SampleClass{

  public static void main(String[] args){
  
    List<String> ar =
    new ArrayList<>();
    
    ar = Collections.synchronizedList(ar);
    
    //operations like add and remove
    //are now implicitly synchronized
    ar.add("Carrot");
    ar.add("Orange");
    ar.add("Apple");
    
    //When traversing a list that is
    //synchronized by synchronizedList()
    //using Iterator, splitIterator, Stream
    //then, we need to enclose the iteration
    //in a synchronized block or method
    synchronized(ar){
    
      Iterator<String> it = ar.iterator();
      
      while(it.hasNext())
        System.out.println(it.next());
    }
    
  }
}

Result
Carrot
Orange
Apple
unmodifiable...() Methods

Methods like unmodifiableList(), unmodifiableSet() and unmodifiableMap() return an unmodifiable view of a collection. In this topic, I'm gonna explain unmodifiableList() method.
Method form: public static <T> List<T> unmodifiableList(List<? extends T> list)

This method returns an unmodifiable view of the specified list. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException.

The returned list will be serializable if the specified list is serializable. Similarly, the returned list will implement RandomAccess if the specified list does.

This example demonstrates unmodifiableList() method.
import java.util.Collections;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SampleClass{

  public static void main(String[] args){
  
    List<String> ar =
    new ArrayList<>();
    
    ar.add("Carrot");
    ar.add("Orange");
    ar.add("Apple");
    
    ar = Collections.unmodifiableList(ar);
    
    //Will throw an UnsupportedOperationException
    //ar.add("Apple");
    
    Iterator<String> it = ar.iterator();
      
    while(it.hasNext())
      System.out.println(it.next());
    
  }
}

No comments:

Post a Comment