Руководство Java SortedSet
1. SortedSet
SortedSet - это подинтерфейс of Set, поэтому он имеет полные характеристики of Set. Разница заключается в том, что SortedSet элементы сортируются в порядке возрастания в соответствии с их естественным порядком или спредоставленным Comparator.
SortedSet сортирует элементы в порядке возрастания.
public interface SortedSet<E> extends Set<E>
Ниже приведено сравнение между Set и SortedSet:
Set<E> | SortedSet<E> / NavigableSet<E> |
Дубликаты элементов не допускаются. Если вы намеренно добавите 1 повторяющийсяэлемент в Set, это действие будет проигнорировано. | Дубликаты элементов не допускаются. Если вы намеренно добавите 1 повторяющийся элемент в SortdSet, это действие будет проигнорировано. |
Допускает не более одного элемента null. | Допускает не более одного элемента null. |
Порядок элементов не гарантируется. | Порядок элементов гарантируется. |
Все элементы SortedSet должны иметь тип Comparable (Сравнимый), или вы должны предоставить Comparator (Компаратор) для SortedSet, чтобы он сравнивал элементы. В противном случае будет вызвано исключение ClassCastException.
Таким образом, при добавлении элемента в SortedSet вы не можете указать его позицию. Позиция вставленного элемента определяется его естественным порядком или предоставленным Comparator.
- Collection
- Set
- NavigableSet
- List
- Queue
- BlockingQueue
- BlockingDeque
- Deque
- TransferQueue
- TreeSet
- ConcurrentSkipListSet
- HashSet
- LinkedHashSet
- CopyOnWriteArraySet
- EnumSet
SortedSet Methods
Comparator<? super E> comparator()
SortedSet<E> subSet(E fromElement, E toElement)
SortedSet<E> headSet(E toElement)
SortedSet<E> tailSet(E fromElement)
E first()
E last()
default Spliterator<E> spliterator()
2. Examples
Следующий класс Employee имитирует сотрудника с информацией о fullName и salary. Класс Employee реализует interface Comparable<Employee>, это означает, что объекты Employee сопоставимы.
Два объекта Employee можно сравнить друг с другом в соответствии с этим правилом: Сравнение по salary, если у них одинаковая salary, для сравнения будет использоваться fullName.
Employee.java
package org.o7planning.bean;
public class Employee implements Comparable<Employee> {
private String fullName;
private float salary;
public Employee(String name, float salary) {
this.fullName = name;
this.salary = salary;
}
public String getFullName() {
return fullName;
}
public float getSalary() {
return salary;
}
// Implements method of Comparable<Employee>
@Override
public int compareTo(Employee o) {
float delta = this.salary - o.salary;
if (delta > 0) {
return 1;
} else if (delta < 0) {
return -1;
}
return this.fullName.compareTo(o.fullName);
}
}
Comparable<Employee>
Например: При использовании TreeSet для хранения объектов Employee они будут отсортированы в порядке возрастания.
SortedSetEx1.java
package org.o7planning.sortedset.ex;
import java.util.SortedSet;
import java.util.TreeSet;
import org.o7planning.bean.Employee;
public class SortedSetEx1 {
public static void main(String[] args) {
Employee e1 = new Employee("Tom A", 5000);
Employee e2 = new Employee("Jerry A", 1000);
Employee e3 = new Employee("Tom B", 1000);
Employee e4 = new Employee("Jerry B", 5000);
Employee e5 = new Employee("Donald A", 1000);
SortedSet<Employee> employees = new TreeSet<Employee>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e4);
employees.add(e5);
for(Employee e: employees) {
System.out.println(e.getSalary() + " / " + e.getFullName());
}
}
}
Output:
1000.0 / Donald A
1000.0 / Jerry A
1000.0 / Tom B
5000.0 / Jerry B
5000.0 / Tom A
Comparable<String>
Объекты String также сопоставимы на основе Alphabet.
SortedSetEx2.java
package org.o7planning.sortedset.ex;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedSetEx2 {
public static void main(String[] args) {
SortedSet<String> flowers = new TreeSet<String>();
flowers.add("Rose");
flowers.add("Lily");
flowers.add("Tulip");
flowers.add("Orchid");
flowers.add("Carnation");
flowers.add("Hyacinth");
flowers.add("Peruvian");
for(String flower: flowers) {
System.out.println(flower);
}
}
}
Output:
Carnation
Hyacinth
Lily
Orchid
Peruvian
Rose
Tulip
Comparator<E>
Следующий класс Staff не реализует interface Comparable, поэтому объекты Staff нельзя сравнивать друг с другом. Если вы хотите хранить объекты Staff в SortedSet, вам необходимо предоставить Comparator.
Staff.java
package org.o7planning.bean;
public class Staff {
private String fullName;
private float salary;
public Staff(String fullName, float salary) {
super();
this.fullName = fullName;
this.salary = salary;
}
public String getFullName() {
return fullName;
}
public float getSalary() {
return salary;
}
}
Класс MyStaffComparator позволяет сравнивать 2 объекта Staff на основе salary и fullName.
MyStaffComparator.java
package org.o7planning.sortedset.ex;
import java.util.Comparator;
import org.o7planning.bean.Staff;
public class MyStaffComparator implements Comparator<Staff> {
@Override
public int compare(Staff o1, Staff o2) {
float delta = o1.getSalary() - o2.getSalary();
if (delta > 0) {
return 1;
} else if (delta < 0) {
return -1;
}
return o1.getFullName().compareTo(o2.getFullName());
}
}
SortedSetEx3.java
package org.o7planning.sortedset.ex;
import java.util.SortedSet;
import java.util.TreeSet;
import org.o7planning.bean.Staff;
public class SortedSetEx3 {
public static void main(String[] args) {
Staff e1 = new Staff("Tom A", 5000);
Staff e2 = new Staff("Tom A", 2000);
Staff e3 = new Staff("Jerry A", 1000);
Staff e4 = new Staff("Tom B", 1000);
Staff e5 = new Staff("Jerry B", 5000);
Staff e6 = new Staff("Donald A", 1000);
// Custom Comparator.
MyStaffComparator comparator = new MyStaffComparator();
// A SortedSet with specified Comparator.
SortedSet<Staff> employees = new TreeSet<Staff>(comparator);
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e4);
employees.add(e5);
employees.add(e6);
for (Staff e : employees) {
System.out.println(e.getSalary() + "/" + e.getFullName());
}
}
}
Output:
1000.0/Donald A
1000.0/Jerry A
1000.0/Tom B
2000.0/Tom A
5000.0/Jerry B
5000.0/Tom A
Comparator - это functional interface, поэтому вы можете создать объект Comparator в Lambda. Хорошо, давайте перепишем приведенный выше пример более кратко:
SortedSetEx3A.java
package org.o7planning.sortedset.ex;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
import org.o7planning.bean.Staff;
public class SortedSetEx3A {
public static void main(String[] args) {
Staff e1 = new Staff("Tom A", 5000);
Staff e2 = new Staff("Tom A", 2000);
Staff e3 = new Staff("Jerry A", 1000);
Staff e4 = new Staff("Tom B", 1000);
Staff e5 = new Staff("Jerry B", 5000);
Staff e6 = new Staff("Donald A", 1000);
// Custom Comparator.
Comparator<Staff> comparator = (s1, s2) -> {
float delta = s1.getSalary() - s2.getSalary();
if (delta > 0) {
return 1;
} else if (delta < 0) {
return -1;
}
return s1.getFullName().compareTo(s2.getFullName());
};
// A SortedSet with specified Comparator.
SortedSet<Staff> employees = new TreeSet<Staff>(comparator);
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e4);
employees.add(e5);
employees.add(e6);
for (Staff e : employees) {
System.out.println(e.getSalary() + "/" + e.getFullName());
}
}
}
3. Null элемент
Спецификация интерфейса SortedSet и NavigableSet вообще не упоминает элементы null, это означает, что они могут допускать не более одного элемента null (наследуемого от спецификации интерфейса Set). Таким образом, разрешают ли SortedSet и NavigabletSet элемент null или нет, зависит от класса, реализующего эти интерфейсы.
В Java Collection Framework класс TreeSet реализует интерфейс NavigableSet, позволяющий обрабатывать элемента null , если вы даете ему Comparator для сравнения элемента null с другими его элементами. Между тем, ConcurrentSkipListSet также реализует интерфейс NavigableSet, но не допускает элемента null t ни в одной ситуации.
Давайте рассмотрим пример, TreeSet и элемент null.
Circle.java
package org.o7planning.bean;
public class Circle {
private double radius;
public Circle(double radius) {
super();
this.radius = radius;
}
public double getRadius() {
return radius;
}
}
Класс CircleComparator реализует интерфейс Comparator<Circle>, который может сравнивать 2 объекта Circle, включая объект null:
CircleComparator.java
package org.o7planning.sortedset.ex;
import java.util.Comparator;
import org.o7planning.bean.Circle;
public class CircleComparator implements Comparator<Circle> {
@Override
public int compare(Circle o1, Circle o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null) {
return -1; // o1 < o2
} else if (o2 == null) {
return 1; // o1 > o2
}
double delta = o1.getRadius() - o2.getRadius();
if (delta < 0) {
return -1; // o1 < o2
} else if (delta > 0) {
return 1; // o1 > o2
}
return 0;
}
}
Например: Объект TreeSet содержит элемент null:
SortedSet_null_element_ex1.java
package org.o7planning.sortedset.ex;
import java.util.TreeSet;
import org.o7planning.bean.Circle;
public class SortedSet_null_element_ex1 {
public static void main(String[] args) {
Circle c1 = new Circle(3);
Circle c2 = new Circle(5);
Circle c3 = new Circle(9);
Circle c4 = new Circle(7);
// Create a SortedSet with provided Comparator.
TreeSet<Circle> set = new TreeSet<Circle>(new CircleComparator());
set.add(null); // Add null Element
set.add(c1);
set.add(c2);
set.add(c3);
set.add(c4);
for (Circle c : set) {
System.out.println("Circle: " + (c == null?null : c.getRadius()));
}
}
}
Output:
Circle: null
Circle: 3.0
Circle: 5.0
Circle: 7.0
Circle: 9.0
4. subSet(E fromElement, E toElement)
public SortedSet<E> subSet(E fromElement, E toElement)
Возвращает представление части этого SortedSet, элементы которого варьируются от fromElement до toElement (fromElement =< element < toElement). (Если fromElement и toElement равны, возвращаемый SortedSet пуст).
Возвращенный SortedSet связан с текущим SortedSet. Изменения в одном SortedSet влияют на другой и наоборот.
SortedSet_subSet_ex1.java
package org.o7planning.sortedset.ex;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedSet_subSet_ex1 {
public static void main(String[] args) {
SortedSet<String> mySet = new TreeSet<String>();
mySet.add("A");
mySet.add("B");
mySet.add("C");
mySet.add("D");
mySet.add("E");
// A Sub Set
SortedSet<String> subSet = mySet.subSet("B", "C1");
System.out.println(" -- subSet --");
for(String s: subSet) {
System.out.println(s);
}
subSet.add("B1");
subSet.add("B2");
System.out.println(" -- subSet (after adding elements to subSet) --");
for(String s: subSet) {
System.out.println(s);
}
System.out.println(" -- mySet (after adding elements to subSet) --");
for(String s: mySet) {
System.out.println(s);
}
}
}
Output:
-- subSet --
B
C
-- subSet (after adding elements to subSet) --
B
B1
B2
C
-- mySet (after adding elements to subSet) --
A
B
B1
B2
C
D
E
5. headSet(E toElement)
public SortedSet<E> headSet(E toElement)
Возвращает представление части этого SortedSet, элементы которой меньше, чем toElement. (element < toElement)
Возвращенный SortedSet связан с текущим SortedSet. Изменения в одном SortedSet влияют на другой и наоборот.
Например:
SortedSet_headSet_ex1.java
package org.o7planning.sortedset.ex;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedSet_headSet_ex1 {
public static void main(String[] args) {
SortedSet<String> mySet = new TreeSet<String>();
mySet.add("A");
mySet.add("B");
mySet.add("C");
mySet.add("D");
mySet.add("D1");
mySet.add("E");
// A Head Set (elements < "D1")
SortedSet<String> headSet = mySet.headSet("D1");
System.out.println(" -- headSet --");
for (String s : headSet) {
System.out.println(s);
}
}
}
Output:
-- headSet --
A
B
C
D
Руководства 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