Lớp Collections trong Java (Collections Utility Class)

Table of Contents

1. Sự khác nhau giữa Collection và Collections?

Collection là một interface cấp cao nhất nhất của Collection Framework. Trong khi đó, Collections là một lớp tiện ích. Collections bao gồm các phương thức static được sử dụng để thao tác trên các đối tượng của Collection (ListArrayListLinkedListMapSet, …).

Interface java.util.Collection được định nghĩa như sau:

public interface Collection<E> extends Iterable<E>{
 
}

Interface java.util.Collections được định nghĩa như sau:

public class Collections {
 
}

Những điểm quan trọng về lớp Collections trong java là:

  • Lớp Collections hỗ trợ các thuật toán đa hình (polymorphic algorithms) hoạt động trên các collection.
  • Lớp Collections ném một ngoại lệ NullPointerException nếu các collection hoặc các đối tượng lớp cung cấp cho chúng là null.

2. Các thuộc tính của lớp Collections

  • static List EMPTY_LIST: khởi tạo một danh sách trống, không thể thay đổi (immutable).
  • static Map EMPTY_MAP: khởi tạo một map trống, không thể thay đổi (immutable).
  • static Set EMPTY_SET: khởi tạo một tập hợp trống, không thể thay đổi (immutable).

3. Các phương thức của lớp Collections

Phương thcMô t
static <T> boolean addAll(Collection<? super T> c, T… elements)Thêm tất cả các phần tử được chỉ định vào bộ sưu tập được chỉ định.
static <T> Queue<T> asLifoQueue(Deque<T> deque)Trả về chế độ Deque như một hàng đợi Last-in-first-out (Lifo).
static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)Tìm kiếm danh sách được chỉ định cho đối tượng được chỉ định sử dụng thuật toán tìm kiếm nhị phân (binary search).
static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)Tìm kiếm danh sách được chỉ định cho đối tượng được chỉ định sử dụng thuật toán tìm kiếm nhị phân (binary search). Các phần tử so sánh dựa vào bộ so sánh (comparator) đã cung cấp.
static <T> void copy(List<? super T> dest, List<? extends T> src)Sao chép tất cả các phần tử từ một danh sách này sang một danh sách khác.
static boolean disjoint(Collection<?> c1, Collection<?> c2)Trả về true nếu hai bộ sưu tập được chỉ định không có các phần tử chung.
static <T> Enumeration<T> emptyEnumeration()Trả về một Enumeration không có phần tử.
static <T> Iterator<T> emptyIterator()Trả về một trình lặp (Iterator) không có phần tử.
static <T> List<T> emptyList()Trả lại danh sách (list) trống, không thay đổi (immutable).
static <T> ListIterator<T> emptyListIterator()Trả về một ListIterator không có phần tử.
static <K,V> Map<K,V> emptyMap()Trả về map trống, không thay đổi (immutable).
static <T> Set<T> emptySet()Trả về tập hợp (set) rỗng, không thay đổi (immutable).
static <T> void fill(List<? super T> list, T obj)Thay thế tất cả các phần tử của danh sách được chỉ định với phần tử được chỉ định.
static int frequency(Collection<?> c, Object o)Trả về số lượng các phần tử có trong bộ sưu tập được chỉ định bằng đối tượng được chỉ định.
static int indexOfSubList(List<?> source, List<?> target)Trả về vị trí bắt đầu của lần xuất hiện đầu tiên của danh sách mục tiêu được chỉ định trong danh sách nguồn quy định, hoặc -1 nếu không tìm thấy đối tượng chỉ định.
static int lastIndexOfSubList(List<?> source, List<?> target)Trả về vị trí bắt đầu của sự xuất hiện cuối cùng của danh sách mục tiêu được chỉ định trong danh sách nguồn quy định, hoặc -1 nếu  không tìm thấy đối tượng chỉ định.
static <T> ArrayList<T> list(Enumeration<T> e)Trả lại một danh sách mảng có chứa các phần tử được trả về bởi Enumeration xác định theo thứ tự chúng được trả về bởi Enumeration.
static <T extends Object & Comparable<? super T>>  max(Collection<? extends T> coll)Trả về phần tử lớn nhất của bộ sưu tập đã cho, theo trật tự tự nhiên của các phần tử.
static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)Trả về phần tử lớn nhất của bộ sưu tập đã cho, theo thứ tự bởi bộ so sánh được chỉ định.
static <T extends Object & Comparable<? super T>>  min(Collection<? extends T> coll)Trả về phần tử nhỏ nhất của bộ sưu tập đã cho, theo trật tự tự nhiên của các phần tử.
static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)Trả về phần tử nhỏ nhất của bộ sưu tập đã cho, theo thứ tự bởi bộ so sánh được chỉ định.
static <T> List<T> nCopies(int n, T o)Trả lại một danh sách không thay đổi bao gồm n bản sao của đối tượng được chỉ định.
static <E> Set<E> newSetFromMap(Map<E,Boolean> map)Trả về một tập hợp (set) được xác định bởi map được chỉ định.
static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)Thay thế tất cả các lần xuất hiện của một giá trị được chỉ định trong danh sách với một giá trị mới
static void reverse(List<?> list)Đảo ngược thứ tự của các phần tử trong danh sách được chỉ định.
static <T> Comparator<T> reverseOrder()Trả về một trình so sánh là bộ so sánh có thứ tự đảo ngược của trật tự tự nhiên trên một tập hợp các đối tượng thực hiện giao diện Comparable.
static <T> Comparator<T> reverseOrder(Comparator<T> cmp)Trả về một trình so sánh là bộ so sánh có thứ tự ngược lại của bộ so sánh được chỉ định.
static void rotate(List<?> list, int distance)Xoay các phần tử trong danh sách được chỉ định theo khoảng cách xác định.
static void shuffle(List<?> list)Xử lý ngẫu nhiên danh sách được chỉ định, sử dụng nguồn xác định ngẫu nhiên mặc định.
static void shuffle(List<?> list, Random rnd)Xử lý ngẫu nhiên danh sách được chỉ định, sử dụng nguồn xác định ngẫu nhiên cung cấp.
static <T> Set<T> singleton(T o)Trả lại một tập hợp (set) không thay đổi chỉ chứa đối tượng được chỉ định.
static <T> List<T> singletonList(T o)Trả lại một danh sách (list) không thay đổi chỉ chứa đối tượng được chỉ định.
static <K,V> Map<K,V> singletonMap(K key, V value)Trả về một map không thay đổi, ánh xạ chỉ một khoá được chỉ định đến giá trị được chỉ định.
static <T extends Comparable<? super T>>  sort(List<T> list)Sắp xếp danh sách tăng dần theo thứ tự tự nhiên của các phần tử.
static <T> void sort(List<T> list, Comparator<? super T> c)Sắp xếp danh sách được chỉ định theo thứ tự của bộ so sánh được chỉ định.
static void swap(List<?> list, int i, int j)Trao đổi các phần tử tại các vị trí được chỉ định trong danh sách được chỉ định.
static <T> Collection<T> synchronizedCollection(Collection<T> c)Trả về một bộ sưu tập đồng bộ hóa (synchronized) được hỗ trợ bởi bộ sưu tập được chỉ định.
static <T> List<T> synchronizedList(List<T> list)Trả về một danh sách được đồng bộ hóa (synchronized) được hỗ trợ bởi danh sách được chỉ định.
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)Trả về một map được đồng bộ hóa (synchronized) được hỗ trợ bởi map được chỉ định.
static <T> Set<T> synchronizedSet(Set<T> s)Trả về một tập hợp (set) được đồng bộ (synchronized) được hỗ trợ bởi tập hợp được chỉ định.
static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)Trả về bản đồ được sắp xếp theo bản đồ đã được đồng bộ hoá (chủ đề) an toàn theo bản đồ được chỉ định.
static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)Trả về chế độ không thể sửa đổi (unmodifiable) của bộ sưu tập được chỉ định.
static <T> List<T> unmodifiableList(List<? extends T> list)Trả lại chế độ xem không thể sửa đổi (unmodifiable) của danh sách (list) được chỉ định.
static <K,V> Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m)Trả về chế độ không thể sửa đổi (unmodifiable) của map được chỉ định.
static <T> Set<T> unmodifiableSet(Set<? extends T> s)Trả về chế độ không thể sửa đổi (unmodifiable) của tập hợp (set) được chỉ định.

4. Ví dụ sử dụng các phương thức của lớp Collections

4.1. Sử dụng thuộc tính EMPTY và phương thức empty() để khởi tạo Collection rỗng

Các thuộc tính EMPTY_LIST, EMPTY_SET, EMPTY_MAP và các phương thức emptyList()emptySet()emptyMap() được sử dụng để khởi tạo một Collection trống, không thể thay đổi (immutable).

Nếu bạn cố tình thêm, xóa, thay đổi phần tử này, JVM sẽ ném ra ngoại lệ UnsupportedOperationException.

Các thuộc tính và phương thức empty này thường được sử dụng để tránh lỗi NullPointerException khi khởi tạo một Collection null hoặc kết quả trả về của một phương thức là null.

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class CollectionsExample {
    public static void main(String a[]) {
        // Using empty fields
        List<Integer> list1 = Collections.EMPTY_LIST;
        Set<Integer> set1 = Collections.EMPTY_SET;
        Map<Integer, String> map1 = Collections.EMPTY_MAP;
 
        // Can't add element
        // list1.add(10); // throw UnsupportedOperationException
        // set1.add(10); // throw UnsupportedOperationException
        // map1.put(1, "one"); // throw UnsupportedOperationException
 
        // Using empty methods
        List<Integer> list2 = Collections.emptyList();
        Set<Integer> set2 = Collections.emptySet();
        Map<Integer, String> map2 = Collections.emptyMap();
 
        // Can't add element
        // list2.add(10); // throw UnsupportedOperationException
        // set2.add(10); // throw UnsupportedOperationException
        // map2.put(1, "one"); // throw UnsupportedOperationException
         
        // After init
        list2 = new ArrayList<>();
        list2.add(1); // run normally
    }
}

4.2. Sử dụng phương thức addAll() để thêm tất cả các phần tử của một danh sách này vào một danh sách khác

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample1 {
    public static void main(String a[]) {
        List<String> list = new ArrayList<String>();
        list.add("C");
        list.add("Core Java");
        list.add("Advance Java");
        System.out.println("Initial collection value:" + list);
 
        Collections.addAll(list, "Servlet", "JSP");
        System.out.println("After adding elements collection value:" + list);
 
        String[] strArr = { "C#", ".Net" };
        Collections.addAll(list, strArr);
        System.out.println("After adding array collection value:" + list);
    }
}

Kết quả thực thi chương trình trên:

Initial collection value:[C, Core Java, Advance Java]
After adding elements collection value:[C, Core Java, Advance Java, Servlet, JSP]
After adding array collection value:[C, Core Java, Advance Java, Servlet, JSP, C#, .Net]

4.3. Sử dụng phương thức min(), max(), search(), sort(), reverse(), reverseOrder(), reverseOrder(Comparator) với kiểu dữ liệu cơ bản (String, Wrapper)

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class CollectionsExample2 {
    public static void main(String a[]) {
        List<Integer> list = new ArrayList<Integer>();
        list.add(46);
        list.add(67);
        list.add(24);
        list.add(16);
        list.add(8);
        list.add(12);
        System.out.println("Maximum value: " + Collections.max(list));
        System.out.println("Minimum value: " + Collections.min(list));
        System.out.println("Index of value 24 : " + Collections.binarySearch(list, 24));
        System.out.println("Index of value 10 : " + Collections.binarySearch(list, 10));
         
        Collections.sort(list);
        System.out.println("Sorted ASC: " + list);
         
        Collections.reverse(list);
        System.out.println("Sorted DESC: " + list);
         
        Comparator<Integer> compareDesc = Collections.reverseOrder();
        Collections.sort(list, compareDesc);
        System.out.println("Sorted ASC: " + list);
         
        Comparator<Integer> compareAsc = Collections.reverseOrder(compareDesc);
        Collections.sort(list, compareAsc);
        System.out.println("Sorted DESC: " + list);
    }
}

Kết quả thực thi chương trình trên:

Maximum value: 67
Minimum value: 8
Index of value 24 : 2
Index of value 10 : -1
Sorted ASC: [8, 12, 16, 24, 46, 67]
Sorted DESC: [67, 46, 24, 16, 12, 8]
Sorted ASC: [67, 46, 24, 16, 12, 8]
Sorted DESC: [8, 12, 16, 24, 46, 67]

4.4. Sử dụng phương thức min(), max(), search(), sort(), reverse(), reverseOrder(), reverseOrder(Comparator) với kiểu do người dùng tự định nghĩa (Object)

4.4.1. Cung cấp bộ so sánh Comparator

Trong ví dụ này tôi sẽ tạo một lớp Student và cung cấp bộ so sánh Comparator cho Collections xử lý. Chi tiết về Comparator và Comparable các bạn có thể xem thêm bài viết TreeSet và sử dụng Comparable, Comparator trong java.

Student.java

package com.maixuanviet.collections;
 
public class Student {
    private int id;
    private String name;
    private int age;
 
    public Student(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
 
    public int getId() {
        return id;
    }
 
    public String getName() {
        return name;
    }
 
    public int getAge() {
        return age;
    }
}

StudentAgeComparator.java

package com.maixuanviet.collections;
 
import java.util.Comparator;
 
public class StudentAgeComparator implements Comparator<Student> {
 
    @Override
    public int compare(Student o1, Student o2) {
        // sort student's age by ASC
        if (o1.getAge() < o2.getAge()) {
            return -1;
        } else if (o1.getAge() == o2.getAge()) {
            return 0;
        } else {
            return 1;
        }
    }
}
&#91;/code&#93;
<!-- /wp:shortcode -->

<!-- wp:paragraph -->
<p>CollectionsExample3.java</p>
<!-- /wp:paragraph -->

<!-- wp:shortcode -->

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class CollectionsExample3 {
    public static void main(String a[]) {
        // Create list
        List<Student> students = new ArrayList<>();
        Student student1 = new Student(1, "myname1", 15);
        Student student2 = new Student(2, "myname2", 20);
        Student student3 = new Student(3, "myname3", 17);
        Student student4 = new Student(4, "myname4", 10);
        Student student5 = new Student(5, "myname5", 19);
        Student student6 = new Student(6, "myname6", 19);
        students.add(student3);
        students.add(student1);
        students.add(student2);
        students.add(student5);
        students.add(student4);
 
        // Init comparator
        StudentAgeComparator ageComparator = new StudentAgeComparator();
 
        // Using comparator
        System.out.println("Maximum value: " + Collections.max(students, ageComparator));
        System.out.println("Minimum value: " + Collections.min(students, ageComparator));
        System.out.println("Index of student1 : " + Collections.binarySearch(students, student1, ageComparator));
        System.out.println("Index of student6 : " + Collections.binarySearch(students, student6, ageComparator));
        System.out.println("---");
 
        Collections.sort(students, ageComparator);
        System.out.println("Sorted ASC: ");
        print(students);
 
        Collections.reverse(students);
        System.out.println("Sorted DESC: ");
        print(students);
 
        Comparator<Student> compareDesc = Collections.reverseOrder(ageComparator);
        Collections.sort(students, compareDesc);
        System.out.println("Sorted DESC: ");
        print(students);
 
        Comparator<Student> compareAsc = Collections.reverseOrder(compareDesc);
        Collections.sort(students, compareAsc);
        System.out.println("Sorted ASC: ");
        print(students);
    }
 
    private static void print(List<Student> students) {
        for (Student student : students) {
            System.out.println(student);
        }
        System.out.println("---");
    }
}

Kết quả thực thi chương trình trên:

Maximum value: Student [id=2, name=myname2, age=20]
Minimum value: Student [id=4, name=myname4, age=10]
Index of student1 : -1
Index of student6 : -3
---
Sorted ASC: 
Student [id=4, name=myname4, age=10]
Student [id=1, name=myname1, age=15]
Student [id=3, name=myname3, age=17]
Student [id=5, name=myname5, age=19]
Student [id=2, name=myname2, age=20]
---
Sorted DESC: 
Student [id=2, name=myname2, age=20]
Student [id=5, name=myname5, age=19]
Student [id=3, name=myname3, age=17]
Student [id=1, name=myname1, age=15]
Student [id=4, name=myname4, age=10]
---
Sorted DESC: 
Student [id=2, name=myname2, age=20]
Student [id=5, name=myname5, age=19]
Student [id=3, name=myname3, age=17]
Student [id=1, name=myname1, age=15]
Student [id=4, name=myname4, age=10]
---
Sorted ASC: 
Student [id=4, name=myname4, age=10]
Student [id=1, name=myname1, age=15]
Student [id=3, name=myname3, age=17]
Student [id=5, name=myname5, age=19]
Student [id=2, name=myname2, age=20]
---

4.4.2. Cung cấp bộ so sánh Comparable

Student2.java

package com.maixuanviet.collections;
 
public class Student2 implements Comparable<Student2> {
    private int id;
    private String name;
    private int age;
 
    public Student2(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }
 
    @Override
    public int compareTo(Student2 student) {
        // sort student's age by ASC
        if (this.getAge() < student.getAge()) {
            return -1;
        } else if (this.getAge() == student.getAge()) {
            return 0;
        } else {
            return 1;
        }
    }
 
    @Override
    public String toString() {
        return "Student &#91;id=" + id + ", name=" + name + ", age=" + age + "&#93;";
    }
 
    public int getId() {
        return id;
    }
 
    public String getName() {
        return name;
    }
 
    public int getAge() {
        return age;
    }
}
&#91;/code&#93;
<!-- /wp:shortcode -->

<!-- wp:paragraph -->
<p>CollectionsExample4.java</p>
<!-- /wp:paragraph -->

<!-- wp:shortcode -->

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class CollectionsExample4 {
    public static void main(String a[]) {
        // Create list
        List<Student2> students = new ArrayList<>();
        Student2 student1 = new Student2(1, "myname1", 15);
        Student2 student2 = new Student2(2, "myname2", 20);
        Student2 student3 = new Student2(3, "myname3", 17);
        Student2 student4 = new Student2(4, "myname4", 10);
        Student2 student5 = new Student2(5, "myname5", 19);
        Student2 student6 = new Student2(6, "myname6", 19);
        students.add(student3);
        students.add(student1);
        students.add(student2);
        students.add(student5);
        students.add(student4);
 
        // Không cần cung cấp bộ so sánh, bởi vì nó đã được cài đặt trong lớp Student2
        System.out.println("Maximum value: " + Collections.max(students));
        System.out.println("Minimum value: " + Collections.min(students));
        System.out.println("Index of student1 : " + Collections.binarySearch(students, student1));
        System.out.println("Index of student6 : " + Collections.binarySearch(students, student6));
        System.out.println("---");
 
        Collections.sort(students);
        System.out.println("Sorted ASC: ");
        print(students);
 
        Collections.reverse(students);
        System.out.println("Sorted DESC: ");
        print(students);
 
        Comparator<Student2> compareDesc = Collections.reverseOrder();
        Collections.sort(students, compareDesc);
        System.out.println("Sorted DESC: ");
        print(students);
 
        Comparator<Student2> compareAsc = Collections.reverseOrder(compareDesc);
        Collections.sort(students, compareAsc);
        System.out.println("Sorted ASC: ");
        print(students);
    }
 
    private static void print(List<Student2> students) {
        for (Student2 student : students) {
            System.out.println(student);
        }
        System.out.println("---");
    }
}

Kết quả thực thi chương trình trên:

Maximum value: Student [id=2, name=myname2, age=20]
Minimum value: Student [id=4, name=myname4, age=10]
Index of student1 : -1
Index of student6 : -3
---
Sorted ASC: 
Student [id=4, name=myname4, age=10]
Student [id=1, name=myname1, age=15]
Student [id=3, name=myname3, age=17]
Student [id=5, name=myname5, age=19]
Student [id=2, name=myname2, age=20]
---
Sorted DESC: 
Student [id=2, name=myname2, age=20]
Student [id=5, name=myname5, age=19]
Student [id=3, name=myname3, age=17]
Student [id=1, name=myname1, age=15]
Student [id=4, name=myname4, age=10]
---
Sorted DESC: 
Student [id=2, name=myname2, age=20]
Student [id=5, name=myname5, age=19]
Student [id=3, name=myname3, age=17]
Student [id=1, name=myname1, age=15]
Student [id=4, name=myname4, age=10]
---
Sorted ASC: 
Student [id=4, name=myname4, age=10]
Student [id=1, name=myname1, age=15]
Student [id=3, name=myname3, age=17]
Student [id=5, name=myname5, age=19]
Student [id=2, name=myname2, age=20]
---

4.5. Sử dụng phương thức frequency() để đếm số lần xuất hiện của phần tử trong Collection

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample5 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(10);
        myList.add(20);
        myList.add(10);
        myList.add(20);
        myList.add(30);
        myList.add(10);
        System.out.println("Elements of ArrayList: " + myList);
        System.out.println("No. of times 10 exists: " + Collections.frequency(myList, 10));
        System.out.println("No. of times 20 exists: " + Collections.frequency(myList, 20));
        System.out.println("No. of times 30 exists: " + Collections.frequency(myList, 30));
    }
}

Kết quả thực thi chương trình trên:

Elements of ArrayList: [10, 20, 10, 20, 30, 10]
No. of times 10 exists: 3
No. of times 20 exists: 2
No. of times 30 exists: 1

4.6. Sử dụng phương thức copy() để sao chép một list này sang một list khác

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample6 {
    public static void main(String args[]) {
        List<String> firstList = new ArrayList<>();
        firstList.add("10");
        firstList.add("20");
        firstList.add("30");
        System.out.println("Elements firstList: " + firstList);
 
        List<String> secondList = new ArrayList<>();
        secondList.add("one");
        secondList.add("two");
        secondList.add("three");
        System.out.println("Elements secondList: " + secondList);
 
        Collections.copy(secondList, firstList);
        System.out.println("Elements of secondList after copying firstList: " + secondList);
 
        List<String> thirdList = new ArrayList<>();
        thirdList.add("one");
        thirdList.add("two");
        thirdList.add("three");
        thirdList.add("four");
        thirdList.add("five");
        System.out.println("\nElements thirdList: " + thirdList);
 
        Collections.copy(thirdList, firstList);
        System.out.println("Elements of thirdList after copying firstList: " + thirdList);
    }
}

Kết quả thực thi chương trình trên:

Elements firstList: [10, 20, 30]
Elements secondList: [one, two, three]
Elements of secondList after copying firstList: [10, 20, 30]
 
Elements thirdList: [one, two, three, four, five]
Elements of thirdList after copying firstList: [10, 20, 30, four, five]

4.7. Sử dụng phương thức swap() để hoán đổi vị trí của 2 phần tử

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample7 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(50);
        myList.add(10);
        myList.add(20);
        myList.add(40);
        System.out.println("Elements before swap: " + myList);
 
        Collections.swap(myList, 0, 1);
        System.out.println("Elements after 0,1 swap: " + myList);
 
        Collections.swap(myList, 2, 3);
        System.out.println("Elements after 2,3 swap: " + myList);
    }
}

Kết quả thực thi chương trình trên:

Elements before swap: [50, 10, 20, 40]
Elements after 0,1 swap: [10, 50, 20, 40]
Elements after 2,3 swap: [10, 50, 40, 20]

4.8. Sử dụng phương thức shuffle() để truy cập ngẫu nhiên các phần tử trong Collection

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample8 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(30);
        myList.add(10);
        myList.add(20);
        myList.add(40);
        System.out.println("Elements before shuffle: " + myList);
 
        Collections.shuffle(myList);
        System.out.println("Elements after first shuffle: " + myList);
 
        Collections.shuffle(myList);
        System.out.println("Elements after second shuffle: " + myList);
 
        Collections.shuffle(myList);
        System.out.println("Elements after third shuffle: " + myList);
    }
}

Kết quả thực thi chương trình trên:

Elements before shuffle: [30, 10, 20, 40]
Elements after first shuffle: [10, 40, 20, 30]
Elements after second shuffle: [10, 20, 40, 30]
Elements after third shuffle: [40, 30, 10, 20]

4.9. Sử dụng phương thức rotate() để xoay các phần tử trong danh sách

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample9 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(10);
        myList.add(20);
        myList.add(30);
        myList.add(40);
        myList.add(50);
        myList.add(60);
        System.out.println("Elements myList before rotate: " + myList);
 
        Collections.rotate(myList, 3);
        System.out.println("Elements myList after rotate: " + myList);
    }
}

Kết quả thực thi chương trình trên:

Elements myList before rotate: [10, 20, 30, 40, 50, 60]
Elements myList after rotate: [40, 50, 60, 10, 20, 30]

4.10. Sử dụng phương thức replaceAll() để tìm kiếm và thay thế các phần tử bằng một phần tử khác

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample10_2 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(10);
        myList.add(20);
        myList.add(30);
        myList.add(40);
        System.out.println("Elements myList before replacing: " + myList);
 
        boolean success = Collections.replaceAll(myList, 10, 100);
        System.out.println("Replace operation successful: " + success);
        System.out.println("Elements after replacing: " + myList);
 
        success = Collections.replaceAll(myList, 50, 200);
        System.out.println("Replace operation successful: " + success);
        System.out.println("Elements after replacing: " + myList);
    }
}

Kết quả thực thi chương trình trên:

Elements myList before replacing: [10, 20, 30, 40]
Replace operation successful: true
Elements after replacing: [100, 20, 30, 40]
Replace operation successful: false
Elements after replacing: [100, 20, 30, 40]

4.11. Sử dụng phương thức fill() để thay thế tất cả các phần tử trong danh sách bằng một phần tử bất kỳ

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample10 {
    public static void main(String args[]) {
        List<Integer> myList = new ArrayList<>();
        myList.add(10);
        myList.add(20);
        myList.add(30);
        myList.add(40);
        System.out.println("Elements before fill: " + myList);
 
        Collections.fill(myList, 0);
        System.out.println("Elements after fill: " + myList);
 
        List<String> namesList = new ArrayList<>();
        namesList.add("wellcome");
        namesList.add("to");
        namesList.add("maixuanviet");
        System.out.println("\nElements before fill: " + namesList);
 
        Collections.fill(namesList, null);
        System.out.println("Elements after fill: " + namesList);
    }
}

Kết quả thực thi chương trình trên:

Elements before fill: [10, 20, 30, 40]
Elements after fill: [0, 0, 0, 0]
 
Elements before fill: [wellcome, to, gpcoder]
Elements after fill: [null, null, null]

4.12. Sử dụng phương thức disjoint() để kiểm tra hai danh sách có chứa bất kỳ phần tử nào giống nhau không

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample11 {
    public static void main(String args[]) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(10);
        list1.add(20);
        list1.add(30);
 
        List<Integer> list2 = new ArrayList<>();
        list2.add(60);
        list2.add(40);
        list2.add(20);
 
        List<Integer> list3 = new ArrayList<>();
        list3.add(60);
        list3.add(40);
        list3.add(50);
 
        System.out.println("Elements of list1: " + list1);
        System.out.println("Elements of list2: " + list2);
        System.out.println("Elements of list3: " + list3);
 
        boolean exists = Collections.disjoint(list1, list2);
        System.out.println("\nlist1 and list2 contains same elements: " + exists); // false
 
        exists = Collections.disjoint(list1, list3);
        System.out.println("list1 and list3 contains same elements: " + exists); // true
    }
}

Kết quả thực thi chương trình trên:

Elements of firstList: [10, 20, 30]
Elements of secondList: [60, 40, 20]
Elements of thirdList: [60, 40, 50]
 
firstList and secondList contains same elements: false
firstList and thirdList contains same elements: true

4.13. Sử dụng phương thức indexOfSubList() và lastIndexOfSubList() để tìm vị trí xuất hiện đầu tiên và cuối cùng của một danh sách này trong một danh sách khác

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class CollectionsExample12 {
    public static void main(String args[]) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(10);
        list1.add(20);
        list1.add(30);
        list1.add(40);
        list1.add(100);
        list1.add(20);
        list1.add(30);
        list1.add(400);
 
        List<Integer> list2 = new ArrayList<>();
        list2.add(20);
        list2.add(30);
 
        List<Integer> list3 = new ArrayList<>();
        list3.add(20);
        list3.add(40);
 
        System.out.println("list1 elements: " + list1);
        System.out.println("list2 elements: " + list2);
        System.out.println("list3 elements: " + list3);
         
        int num1 = Collections.indexOfSubList(list1, list2);
        System.out.println("\nFirst index list2 in list1: " + num1);
 
        int num2 = Collections.lastIndexOfSubList(list1, list2);
        System.out.println("Last index list2 in list1: " + num2);
 
        int num3 = Collections.lastIndexOfSubList(list1, list3);
        System.out.println("\nFirst index num3 in list1: " + num3);
 
        int num4 = Collections.lastIndexOfSubList(list1, list3);
        System.out.println("Last index num3 in list1: " + num4);
    }
}

Kết quả thực thi chương trình trên:

list1 elements: [10, 20, 30, 40, 100, 20, 30, 400]
list2 elements: [20, 30]
list3 elements: [20, 40]
 
First index list2 in list1: 1
Last index list2 in list1: 5
 
First index num3 in list1: -1
Last index num3 in list1: -1

4.14. Sử dụng các phương thức unmodifiableCollection()

Các lớp trong Collection, thông thường khi khởi tạo có thể sửa đổi được (modifiable). Tức là, các phần tử có thể được thêm, xóa hoặc thay thế bất cứ lúc nào. Nhưng đôi khi, nó có thể được yêu cầu để có các lớp chỉ có thể đọc (unmodifiable), bất kỳ sửa đổi phần tử đều không thể được thực hiện. Điều này có thể được thực hiện bằng cách sử dụng phương thức unmodifiableCollection() của lớp tiện ích Collections.

Khi bạn cố gắng sửa đổi phần tử được trả về từ phương thức unmodifiableCollection(), JVM sẽ ném UnsupportedOperationException.

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class CollectionsExample13 {
    public static void main(String args[]) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(10);
        list1.add(20);
        list1.add(30);
        list1.add(40);
 
        List<Integer> list2 = Collections.unmodifiableList(list1);
        System.out.println("list2 elements: " + list2);
 
        // list2.add(50); // throws UnsupportedOpearationException
 
        System.out.println("list1 elements before adding 50: " + list1);
        list1.add(50);
        System.out.println("list1 elements after adding 50: " + list1);
 
        Set<String> set1 = new HashSet<>();
        set1.add("welcome");
        set1.add("to");
        set1.add("gpconder");
        Set<String> set2 = Collections.unmodifiableSet(set1);
        System.out.println("set2 elements: " + set2);
 
        // set2.add("sir"); // throws UnsupportedOpearationException
 
        Map<Integer, String> map1 = new HashMap<>();
        map1.put(1, "one");
        map1.put(2, "two");
        map1.put(3, "three");
        Map<Integer, String> map2 = Collections.unmodifiableMap(map1);
        System.out.println("map2 elements: " + map2);
 
        // map2.put(4, "four"); // throws UnsupportedOpearationException
    }
}

Kết quả thực thi chương trình trên:

list2 elements: [10, 20, 30, 40]
list1 elements before adding 50: [10, 20, 30, 40]
list1 elements after adding 50: [10, 20, 30, 40, 50]
set2 elements: [gpconder, to, welcome]
map2 elements: {1=one, 2=two, 3=three}

4.15. Ví dụ sử dụng synchronizedCollection() để sử dụng các phương thức của Collection trong môi trường đa luồng (multi-thread)

Các phương thức của lớp kế thừa từ Collection như Vector và Hashtable được đồng bộ hóa ngầm (synchronized). Nó hợp nhất cho thao tác với luồng an toàn (thread-safe). Một thao tác được gọi là an toàn khi nhiều luồng truy cập dữ liệu, dữ liệu không bị hỏng hoặc dẫn đến sự không nhất quán. Đó là biện pháp phòng ngừa được thực hiện trong một môi trường đa luồng. Tuy nhiên, các lớp Collection không phải là thread-safe vì các phương thức của chúng không được đồng bộ. Nhờ có lớp Collections cung cấp cho chúng ta phương thức synchronizedCollection() và trả về một đối tượng khác của Collection với phương thức đồng bộ.

Với các lớp Collection, chúng ta có một sự lựa chọn để có phiên bản đồng bộ hóa hoặc không đồng bộ. Nhưng trong trường hợp Vector và Hashtable thì không thể làm được điều này, nó chỉ có phiên bản được đồng bộ hóa.

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class CollectionsExample14 {
    public static void main(String args[]) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(10);
        list1.add(20);
        list1.add(30);
        list1.add(40);
 
        List<Integer> list2 = Collections.synchronizedList(list1);
        System.out.println("list2 elements: " + list2);
 
        HashSet<String> set1 = new HashSet<String>();
        set1.add("welcome");
        set1.add("to");
        set1.add("gpconder");
        Set<String> set2 = Collections.synchronizedSet(set1);
        System.out.println("set2 elements: " + set2);
 
        Map<Integer, String> map1 = new HashMap<>();
        map1.put(1, "one");
        map1.put(2, "two");
        map1.put(3, "three");
        Map<Integer, String> map2 = Collections.synchronizedMap(map1);
        System.out.println("map2 elements: " + map2);
    }
}

Kết quả thực thi chương trình trên:

list2 elements: [10, 20, 30, 40]
set2 elements: [gpconder, to, welcome]
map2 elements: {1=one, 2=two, 3=three}

4.16. Sử dụng phương thức checkedCollection() để sử dụng Type-safe Collection (tương tự Generic)

JDK 1.5 bổ sung thêm một tính năng gọi là Generics cho các lớp Collection (JDK 1.2). Với Generics, chúng ta chỉ có thể thêm một loại dữ liệu vào một cấu trúc dữ liệu. Nhưng các lớp kế thừa (legacy class), được giới thiệu với JDK 1.0, như Vector hay Hashtable thì không sử dụng được. Để khắc phục điều này, lớp Collections cung cấp phương thức checkedCollection() và trả về một đối tượng Collection khác hoạt động như các Generics, có khả năng lưu trữ chỉ một loại dữ liệu.

Khi thao tác với đối tượng Collection này, nếu một phần tử với kiểu dữ liệu khác được thêm vào, JVM sẽ ném ClassCastException.

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class CollectionsExample15 {
    public static void main(String args[]) {
        List list1 = new ArrayList();
        list1.add(10);
        list1.add(20);
        list1.add(30);
        list1.add(40);
 
        List list2 = Collections.checkedList(list1, Integer.class);
        System.out.println("list2 elements: " + list2);
 
        list1.add("hello");
        // list2.add("hello"); // throws ClassCastException
 
        HashSet set1 = new HashSet();
        set1.add("welcome");
        set1.add("to");
        set1.add("gpconder");
        Set set2 = Collections.checkedSet(set1, String.class);
        System.out.println("set2 elements: " + set2);
 
        set1.add(10);
        // secondSet.add(10); // throws ClassCastException
 
        Map map1 = new HashMap();
        map1.put(1, "one");
        map1.put(2, "two");
        map1.put(3, "three");
        Map map2 = Collections.checkedMap(map1, Integer.class, String.class);
        System.out.println("map2 elements: " + map2);
 
        // map2.put("4", "four"); // throws ClassCastException
    }
}

Kết quả thực thi chương trình trên:

list2 elements: [10, 20, 30, 40]
set2 elements: [gpconder, to, welcome]
map2  elements: {1=one, 2=two, 3=three}

4.17. Sử dụng phương thức singletonList() để đảm bảo một đối tượng chỉ có một phần tử

Với lớp singleton, bạn chỉ có thể tạo ra một đối tượng. Nếu một đối tượng khác được tạo ra, JVM sẽ ném UnsupportedOperationException. Một lớp Singleton chỉ chứa một phần tử. Nếu bạn cố thêm một phần tử thứ hai, phương thức add() sẽ ném UnsupportedOperationException.

Lớp Singleton giới hạn các nhà phát triển khởi tạo nhiều hơn một đối tượng. Ý tưởng này rất hữu ích khi chỉ có một đối tượng là đủ, trong một lớp, để phối hợp tất cả các hành động của lớp.

Một lớp singleton không thể là một interface. Một danh sách singleton chỉ chứa một phần tử và một HashMap singleton chỉ chứa một khoá. Một đối tượng singleton là bất biến (immutable), không thể sửa đổi để thêm một phần tử, tránh sử dụng add().

Để có được một lớp singleton từ một lớp Collection chung, chúng ta sử dụng phương thức singletonList() của Collections được sử dụng.

package com.maixuanviet.collections;
 
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class CollectionsExample16 {
    public static void main(String args[]) {
        List<Integer> list = Collections.singletonList(new Integer(10));
        System.out.println("list elements: " + list);
 
        // list.add(20); // throws UnsupportedOperationException
 
        Set<String> set = Collections.singleton("Welcome to maixuanviet.com");
        System.out.println("set elements: " + set);
 
        // set.add("world"); // throws UnsupportedOperationException
 
        Map<Integer, String> map = Collections.singletonMap(1, "one");
        System.out.println("map elements: " + map);
 
        // map1.put(2, "two"); // throws UnsupportedOperationException
    }
}

Kết quả thực thi chương trình trên:

list elements: [10]
set elements: [Welcome to gpcoder.com]
map elements: {1=one}

4.18. Sử dụng phương thức list(Enumeration) để chuyển Enumeration sang ArrayList

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Vector;
 
public class CollectionsExample17 {
    public static void main(String args[]) {
        Vector<Integer> vect = new Vector<>();
        vect.addElement(10);
        vect.addElement(30);
        vect.add(50);
        vect.add(20);
        System.out.println("Elements of Vector: " + vect);
 
        Enumeration<Integer> e = vect.elements();
        ArrayList<Integer> myList = Collections.list(e);
        System.out.println("Elements of ArrayList: " + myList);
    }
}

Kết quả thực thi chương trình trên:

Elements of Vector: [10, 30, 50, 20]
Elements of ArrayList: [10, 30, 50, 20]

4.19. Sử dụng phương thức enumeration() để có thể duyệt các phần tử của Collection thông qua đối tượng Enumeration

package com.maixuanviet.collections;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
 
public class CollectionsExample18 {
    public static void main(String args[]) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(10);
        list1.add(20);
        list1.add(30);
        list1.add(40);
        System.out.println("list1 elements: " + list1);
 
        Enumeration<Integer> e = Collections.enumeration(list1);
 
        System.out.print("list1 elements using Enumeration: ");
        while (e.hasMoreElements()) {
            Object obj = e.nextElement();
            System.out.print(obj + " ");
        }
    }
}

Kết quả thực thi chương trình trên:

list1 elements: [10, 20, 30, 40]
list1 elements using Enumeration: 10 20 30 40