betacode

Руководство Java SortedSet

  1. SortedSet
  2. Examples
  3. Null элемент
  4. subSet(E fromElement, E toElement)
  5. headSet(E toElement)
  6. tailSet(E fromElement)
  7. spliterator()
  8. first()
  9. last()

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.
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

6. tailSet(E fromElement)

public SortedSet<E> tailSet(E fromElement)
Возвращает представление части этого SortedSet, элементы которой больше или равны fromElement. (element >= fromElement).
Возвращенный SortedSet связан с текущим SortedSet. Изменения в одном SortedSet влияют на другой и наоборот.

7. spliterator()

public default Spliterator<E> spliterator()
  • Руководство Java Spliterator

8. first()

public E first()
Возвращает первый элемент (наименьший) of SortedSet.

9. last()

public E last()
Возвращает последний элемент (самый большой) SortedSet.