Руководство Java Set
1. Set
Set - это интерфейс в Java коллекции (Java Collection Framework) и является подинтерфейсом Collection, поэтому он обладает всеми функциями Collection.
Set- это неупорядоченная Collection(unordered Collection), не допускающая дублирования элементов и содержащая максимум 1 null-элемент. Если вы намеренно добавите дублированный элемент в Set, это действие будет проигнорировано и Set не изменится.
public interface Set<E> extends Collection<E>
SortedSet- это подинтерфейс Set. Он имеет возможность автоматически сортировать элементы по их естественному порядку или по предоставленному Comparator.
- Collection
- Queue
- List
- SortedSet
- NavigableSet
- TransferQueue
- BlockingQueue
- BlockingDeque
- Deque
Иерархия классов реализует (implement) interface Set.
- HashSet
- LinkedHashSet
- TreeSet
- ConcurrentSkipListSet
- CopyOnWriteArraySet
- Spliterators
- EnumSet
Методы interface Set:
Set interface
boolean add(E e)
boolean addAll(Collection<? extends E> c)
void clear()
boolean contains(Object o)
boolean containsAll(Collection<?> c)
boolean equals(Object o)
int hashCode()
boolean isEmpty()
int size()
boolean remove(Object o)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)
Object[] toArray()
<T> T[] toArray(T[] a)
Iterator<E> iterator()
default Spliterator<E> spliterator()
static <E> Set<E> copyOf(Collection<? extends E> coll)
static <E> Set<E> of()
static <E> Set<E> of(E e1)
static <E> Set<E> of(E... elements)
static <E> Set<E> of(E e1, E e2)
static <E> Set<E> of(E e1, E e2, E e3)
static <E> Set<E> of(E e1, E e2, E e3, E e4)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
2. Simple Examples
Set- это interface, поэтому для создания объекта Set необходимо создать класс, который его реализует, например HashSet, LinkedHashSet, TreeSet и т. д.
В следующем примере мы создаем объект HashSet с начальной емкостью (capacity) 10 элементов, и емкость увеличится на 80%, если его количество элементов превысит текущую емкость.
SetEx1.java
package org.o7planning.set.ex;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetEx1 {
public static void main(String[] args) {
Set<String> set = new HashSet<String>(10, (float) 0.8);
set.add("One");
set.add("Two");
set.add("Three");
Iterator<String> it1 = set.iterator();
while (it1.hasNext()) {
System.out.println(it1.next());
}
System.out.println(" ----- ");
// When duplication occurs.
// It will add new element and remove old element.
set.add("Two");
set.add("Four");
Iterator<String> it2 = set.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
}
}
}
Примечание:Set- это неупорядоченная Collection (unordered Collection), поэтому при печати элементов на Console вы можете получить немного другой результат.
Output:
One
Two
Three
-----
One
Four
Two
Three
Array --> Set?
Пример преобразования массива в объект Set.
ArrayToSetEx.java
package org.o7planning.set.ex;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ArrayToSetEx {
public static void main(String[] args) {
Integer[] sourceArray = { 0, 3, 5, 3, 4, 5 };
Set<Integer> targetSet = new HashSet<Integer>(Arrays.asList(sourceArray));
for(Integer i : targetSet) {
System.out.println(i);
}
}
}
Output:
0
3
4
5
3. stream()
Set - это подинтерфейс Collection, поэтому он наследует метод stream(). Доступ к элементам Collection через Stream делает ваш код кратким и легким для понимания:
- Collection
- Stream
Set_stream.java
package org.o7planning.set.ex;
import java.util.HashSet;
import java.util.Set;
public class Set_stream {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a1");
set.add("b1");
set.add("a2");
set.add("c1");
set.add("d1");
set.add("e1");
set.stream() //
.map(String::toUpperCase) // to upsercase
.filter(s -> !s.startsWith("A")) // Not starts with "A".
.forEach(System.out::println);
}
}
Output:
E1
D1
C1
B1
4. iterator()
iterator() - это метод, наследующий от Collection, возвращающий объект Iterator для итерации (iterate) элементов Collection.
Iterator<E> iterator()
Set_iterator.java
package org.o7planning.set.ex;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Set_iterator {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a1");
set.add("b1");
set.add("a2");
Iterator<String> ite = set.iterator();
while(ite.hasNext()) {
System.out.println(ite.next());
}
}
}
Output:
a1
a2
b1
5. Как Set проверяет наличие дублирования?
Set- это Collection, которая не позволяет содержать дублированные элементы. Если вы намеренно добавите дублированный элемент в Set, это действие будет проигнорировано. Итак, вопрос в том, как "Set" проверяет дублирование?
SortedSet - это подинтерфейс Set. В этом разделе мы имеем дело только с чистыми типами Set (не SortedSet). Классы, представляющие чистый Set , - это HashSet, LinkedHashSet, CopyOnWriteArraySet и EnumSet.
Способ проверки SortedSet на дублирование полностью отличается от чистого Set и рассматривается в следующей статье:
HashSet / LinkedHashSet
HashSet (и LinkedHashSet) будут сравнивать hashcode(хэш-код) 2 элементов, а затем сравнивать 2 элемента напрямую с помощью их метода equals.
Взгляните на 2 примера HashSetDupTest1 и HashSetDupTest2 ниже, чтобы понять больше о приведенном выше описании.
HashSetDupTest1.java
package org.o7planning.set.test;
import java.util.HashSet;
import java.util.Set;
public class HashSetDupTest1 {
public static class Student {
private int studentId;
private String studentName;
public Student(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
}
public int getStudentId() {
return studentId;
}
public String getStudentName() {
return studentName;
}
@Override
public boolean equals(Object other) {
if(other == null || !(other instanceof Student)) {
return false;
}
Student o = (Student) other;
return this.studentId == o.studentId;
}
}
public static void main(String[] args) {
Student s1 = new Student(1, "Tom");
Student s2 = new Student(2, "Jerry");
Student s3 = new Student(1, "Tom Cat"); // Same Id with s1.
Set<Student> set = new HashSet<Student>();
set.add(s1);
set.add(s2);
set.add(s3);
for(Student s: set) {
System.out.printf("Student Id: %d / Name: %s (Hashcode: %s)\n", //
s.getStudentId(),s.getStudentName(),s.hashCode());
}
}
}
Output:
Student Id: 2 / Name: Jerry (Hashcode: 474675244)
Student Id: 1 / Name: Tom Cat (Hashcode: 932583850)
Student Id: 1 / Name: Tom (Hashcode: 1586600255)
Отредактируйте приведенный выше пример, переопределив (override) метод hashCode() в классе Student:
HashSetDupTest2.java
package org.o7planning.set.test;
import java.util.HashSet;
import java.util.Set;
public class HashSetDupTest2 {
public static class Student {
private int studentId;
private String studentName;
public Student(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
}
public int getStudentId() {
return studentId;
}
public String getStudentName() {
return studentName;
}
@Override
public boolean equals(Object other) {
if(other == null || !(other instanceof Student)) {
return false;
}
Student o = (Student) other;
return this.studentId == o.studentId;
}
@Override
public int hashCode() { // -----> Override hashCode() method.
return this.studentName.charAt(0);
}
}
public static void main(String[] args) {
Student s1 = new Student(1, "Tom"); // Hashcode: 84 ('T')
Student s2 = new Student(1, "Tom Cat"); // Hashcode: 84 ('T')
Student s3 = new Student(2, "Jerry"); // Hashcode: 74 ('J')
Student s4 = new Student(4, "Daffy"); // Hashcode: 68 ('D')
Student s5 = new Student(5, "Donald"); // Hashcode: 68 ('D')
Set<Student> set = new HashSet<Student>();
set.add(s1);
set.add(s2); // a Duplication (Ignored!)
set.add(s3);
set.add(s4);
set.add(s5);
for(Student s: set) {
System.out.printf("Student Id: %d / Name: %s (Hashcode: %s)\n", //
s.getStudentId(),s.getStudentName(),s.hashCode());
}
}
}
Output:
Student Id: 1 / Name: Tom (Hashcode: 84)
Student Id: 4 / Name: Daffy (Hashcode: 68)
Student Id: 5 / Name: Donald (Hashcode: 68)
Student Id: 2 / Name: Jerry (Hashcode: 74)
CopyOnWriteArraySet
CopyOnWriteArraySet напрямую сравнивает 2 элемента с помощью их метода equals.
Взгляните на 2 примера CopyOnWriteArraySetDupTest1 и CopyOnWriteArraySetDupTest2 ниже, чтобы понять больше о приведенном выше описании.
CopyOnWriteArraySetDupTest1.java
package org.o7planning.set.test;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class CopyOnWriteArraySetDupTest1 {
public static class Employee {
private int empId;
private String empName;
public Employee(int empId, String empName) {
this.empId = empId;
this.empName = empName;
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
// Employee class uses equals(Object) method inherited from Object class.
}
public static void main(String[] args) {
Employee s1 = new Employee(1, "Tom");
Employee s2 = new Employee(2, "Jerry");
Employee s3 = new Employee(1, "Tom Cat");
Set<Employee> set = new CopyOnWriteArraySet<Employee>();
set.add(s1);
set.add(s2);
set.add(s3);
for(Employee s: set) {
System.out.printf("Emp Id: %d / Name: %s\n", //
s.getEmpId(),s.getEmpName());
}
}
}
Output:
Emp Id: 1 / Name: Tom
Emp Id: 2 / Name: Jerry
Emp Id: 1 / Name: Tom Cat
Отредактируйте приведенный выше пример, переопределив (override) метод equals(Object) в классе Employee:
CopyOnWriteArraySetDupTest2.java
package org.o7planning.set.test;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class CopyOnWriteArraySetDupTest2 {
public static class Employee {
private int empId;
private String empName;
public Employee(int studentId, String studentName) {
this.empId = studentId;
this.empName = studentName;
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
@Override
public boolean equals(Object other) { // -----> Override equals() method.
if(other == null || !(other instanceof Employee)) {
return false;
}
Employee o = (Employee) other;
return this.empId == o.empId;
}
}
public static void main(String[] args) {
Employee s1 = new Employee(1, "Tom");
Employee s2 = new Employee(2, "Jerry");
Employee s3 = new Employee(1, "Tom Cat");
Set<Employee> set = new CopyOnWriteArraySet<Employee>();
set.add(s1);
set.add(s2);
set.add(s3); // a Duplication.
for(Employee s: set) {
System.out.printf("Emp Id: %d / Name: %s\n", //
s.getEmpId(),s.getEmpName());
}
}
}
Output:
Emp Id: 1 / Name: Tom
Emp Id: 2 / Name: Jerry
6. of(..)
Статический метод Set.of(..) возвращает объект Set фиксированного размера, исключение создается, если входные параметры дублируются. Этот объект Setне поддерживает дополнительные методы: add, remove, set и clear.
static <E> Set<E> of()
static <E> Set<E> of(E e1)
static <E> Set<E> of(E... elements)
static <E> Set<E> of(E e1, E e2)
static <E> Set<E> of(E e1, E e2, E e3)
static <E> Set<E> of(E e1, E e2, E e3, E e4)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
Set_of.java
package org.o7planning.set.ex;
import java.util.Iterator;
import java.util.Set;
public class Set_of {
public static void main(String[] args) {
Set<Integer> set = Set.of(1, 2, 5, 3, 7, 9, 0);
Iterator<Integer> it2 = set.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
}
}
}
Примечание: Set- это неупорядоченная Collection (unordered Collection), поэтому при печати элементов на Console вы можете получить немного другой результат.
Output:
2
3
5
7
9
0
1
7. spliterator()
Создайте объект Spliterator для обхода и разбиения (traversing and partitioning) элементов Set.
default Spliterator<E> spliterator()
Spliteratorшироко используется для обхода и разбиения (traversing and partitioning) различных источников данных, таких как Collection (List, Set, Queue), BaseStream, array.
- Руководство Java Spliterator
8. toArray(..)
Метод toArray(..) возвращает массив, содержащий все элементы Set.
Object[] toArray()
<T> T[] toArray(T[] a)
// Java 11, The default method, inherited from Collection.
default <T> T[] toArray(IntFunction<T[]> generator)
Set_toArray.java
package org.o7planning.set.ex;
import java.util.HashSet;
import java.util.Set;
public class Set_toArray {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a1");
set.add("b1");
set.add("a2");
String[] array = new String[set.size()];
set.toArray(array);
for(String s: array) {
System.out.println(s);
}
}
}
Output:
a1
a2
b1
Руководства Java Collections Framework
- Руководство Java PriorityBlockingQueue
- Руководство Java Collections Framework
- Руководство Java SortedSet
- Руководство Java List
- Руководство Java Iterator
- Руководство Java NavigableSet
- Руководство Java ListIterator
- Руководство Java ArrayList
- Руководство Java CopyOnWriteArrayList
- Руководство Java LinkedList
- Руководство Java Set
- Руководство Java TreeSet
- Руководство Java CopyOnWriteArraySet
- Руководство Java Queue
- Руководство Java Deque
- Руководство Java IdentityHashMap
- Руководство Java WeakHashMap
- Руководство Java Map
- Руководство Java SortedMap
- Руководство Java NavigableMap
- Руководство Java HashMap
- Руководство Java TreeMap
- Руководство Java PriorityQueue
- Руководство Java BlockingQueue
- Руководство Java ArrayBlockingQueue
- Руководство Java TransferQueue
Show More