У меня есть класс Person с каким-то Person, и там есть детали, как там имя, возрастная группа.
Интервал возрастного диапазона составляет {"0-5", "6-10", "11-30", "31-45", "46-50", "50-100", "100-110"};

У меня есть класс Person с name, ageBand строковым интервалом и его параметризованным конструктором, геттерами, сеттерами.

class Person {
    String name;
    String ageBand; //say it is string "0-50" which i pass in constructor while creating a person.
    //getters
    //setters
}
class TestAgeBand {
    public static void main(String args[]) {
        ArrayList<Person> person = new ArrayList<Person>();

        Person p1 = new Person("Mike1", "0-5");   
        Person p2 = new Person("Mike2", "6-10");
        Person p3 = new Person("Mike3", "11-30");   
        Person p4 = new Person("Mike4", "31-45");   
        Person p5 = new Person("Mike5", "50-100");   
        Person p6 = new Person("Mike6", "46-50"); 
        Person p7 = new Person("Mike7", "100-110");

        person.add(p1);
        //adding all persons to list.
    }
}

Вот что я делаю с моим кодом для сортировки интервала. Мне нужно сортировать людей по возрастающим интервалам. Я использую Treemap для сортировки интервалов.

Map<String, Person> ageBandMap = new TreeMap<String, Person>(){
    for(Person p: person) {
        ageBandMap.put(p.ageBand, p.name);
    }
}

Когда я печатаю интервальный набор ключей, я получаю

Выход:

[0-5, 100-110, 11-30, 31-45, 46-50, 50-100, 6-10]

Который мне не нужен. Мне нужны интервалы, отсортированные так:

[0-5, 6-10, 11-30, 31-45, 46-50, 50-100, 100-110]

5
Jabongg 4 Сен 2017 в 14:35

5 ответов

Лучший ответ

Попробуйте разбить вашу строку ageBand и преобразовать ее в Integer, ее будет легче отсортировать.

person.stream().sorted(Comparator.comparing(element -> Integer.parseInt(element.getAgeBand().split("-")[0])))
            .collect(Collectors.toList());

Если вы не хотите использовать Java 8, вы можете сделать это с помощью метода Collections.sort().

 Collections.sort(person, new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            return Integer.parseInt(o1.getAgeBand().split("-")[0]) - Integer.parseInt(o2.getAgeBand().split("-")[0]);
        }
    });
4
Schidu Luca 4 Сен 2017 в 11:46

Мы могли бы попытаться быть очень умными и передать собственный компаратор в TreeMap, который фактически сравнивает диапазоны. Но учтите, что, поскольку ваши диапазоны полностью не перекрываются, мы могли бы просто представить Person, используя нижнее (или даже верхнее) значение его соответствующего диапазона, и получить тот же эффект сортировки. Поэтому я предлагаю следующее:

public class Person {
    String name;
    Integer lower;
    Integer upper;
}

SortedSet<Person> set =
    new TreeSet<Person>(new Comparator<Person>()
    {
        public int compare(Person p1, Person p2) {
            if (p1 == null && p2 == null) return 0;
            if (p1 == null) return -1;
            if (p2 == null) return 1;
            return p1.getLower().compareTo(p2.getLower());
        }
    });
2
dasblinkenlight 4 Сен 2017 в 11:51

Вам необходимо абстрагировать интервал от интерфейса:

interface Interval extends Comparable {

     int left();
     int right();
}

public final class IntervalImpl implements Interval {

     private final int left;
     private final int right;


     public IntervalImpl(int left, int right) {
          this.left = left;
          this.right = right;
     }

     public IntervalImpl(String interval) {
          this.left = Integer.parseInt(interval.split("-")[0]);
          this.right = Integer.parseInt(interval.split("-")[1]);
     }

     @Override
     public int left() { return left; }

     @Override 
     int right() { return right; }

     @Override
     int compareTo(Interval other) {
         return left.compareTo(other.left());
     }

 }

А затем используйте его в своем классе:

 public final class Person {
     private final Interval interval;
     private final String name;

     public Person (String name, String interval) {
          this.name = name;
          this.interval = new Interval(interval);
     }

     public Interval getInterval() {
          return interval;
     }
 }

А затем использовать его в карте:

Map<Interval, Person> map = new TreeMap<>();

Я даже предлагаю перенести ваши интервальные константы в Enum. Сделано внутри вашей Interval абстракции.

0
Izbassar Tolegen 4 Сен 2017 в 11:55

Вот фрагмент кода, который вы хотите:

    Map<String,Person> ageBandMap = new LinkedHashMap<>();
    Map<Integer, Person> ageBandIntMap = new TreeMap<>();

    for(Person p: person)
        ageBandIntMap.put(Integer.parseInt(p.ageBand.split("-")[0]), p);

    for(Entry<Integer, Person> entry : ageBandIntMap.entrySet())
        ageBandMap.put(entry.getValue().ageBand, entry.getValue());

    for(Entry<String, Person> entry : ageBandMap.entrySet())
        System.out.format("\nageBand : %7s\t Person name : %S", entry.getKey(), entry.getValue().name);
0
Gopal 4 Сен 2017 в 12:04

Если вы помещаете значения ключей так, как вы хотите, чтобы они были распечатаны, вы можете использовать LinkedHashMap - он запоминает порядок размещения.

0
SergeiK 4 Сен 2017 в 11:51