2016-06-30 2 views
0

У меня есть класс под названием Doctor со следующими переменными класса: 1. Специальность (Создано перечисление) 2. Area (Создано перечисление) 3. ReviewScore (int)Java - Сортировка HashMap по значению и еще один атрибут

У меня есть отдельный класс, называемый getDoctors, в котором хранится объект ArrayList < Doctor>. В этом классе я определил метод getDistance, который возвращает расстояние (a Double) между данным объектом Doctor и всеми другими объектами Doctor. Затем я создал HashMap, у которого каждый Доктор есть ключ и расстояние от текущего врача в качестве значения. Я пошел вперед и отсортировал этот HashMap по значению.

До этого момента все работает нормально. Теперь, когда значения расстояния одинаковы, я хочу отсортировать этот HashMap на основе переменной класса ReviewScore объектов Doctor.

Любые подсказки о том, как я могу это сделать? Ниже приведен код, который берет в HashMap < Доктор, Double> и сортирует его по значению:

public static <Doctor, Double extends Comparable<? super Double>> HashMap<Doctor, Double> sortByValue(HashMap<Doctor, Double> map){ 
    HashMap<Doctor, Double> result = new LinkedHashMap<>(); 
    Stream<Map.Entry<Doctor, Double>> st = map.entrySet().stream(); 

    st.sorted(Map.Entry.comparingByValue()) 
     .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); 

    return result; 
} 
+2

Вы хотите отсортировать '' 'HashMap'''? Вы не можете, '' 'HashMap''' неупорядочен. –

+4

Почему универсальная декларация каким-либо образом? ('' '>' '') –

+0

@JornVernee Это способ создания кода с удвоением в памяти, а затем изменить его на общий, без модификации тела. –

ответ

4
public static HashMap<Doctor, Double> sortByValue(HashMap<Doctor, Double> map){ 
    return map.entrySet() 
      .stream() 
      .sorted(Map.Entry.<Doctor, Double>comparingByValue().thenComparing(
         Map.Entry.comparingByKey(Comparator.comparingInt(Doctor::getReviewScore)))) 
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)); 
} 
+0

Большое вам спасибо за это! Это действительно помогает. – RajveerParikh

0

У вас есть какая-то ошибка. Double extends Comparable<? super Double> определяет Double как параметр типа. Лучше вы должны использовать только Double. Ошибочно назвать параметр типа таким же, как фактический.

То же наблюдение с Doctor. Вы действительно должны придерживаться соглашения однобуквенных (верхних) имен для параметров типа. Это сразу показало бы вам, что вы вообще не хотите эти параметры типа вообще.

Вы также должны запрограммировать интерфейс.

Чтобы отсортировать карту, вам необходимо использовать https://docs.oracle.com/javase/8/docs/api/java/util/SortedMap.html как https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html, что делает заказ по вашему имени. Используйте конструктор, который принимает Comparator.

Так что вы хотите:

package practice; 

import java.awt.Point; 

public class DoctorDistance { 

    private final String REP_FORMAT = "{%s, %8.2f}"; 

    public static double metric(Point p0, Point p1) { 
     final double xdiff = (double)(p1.getX() - p0.getX()); 
     final double ydiff = (double)(p1.getY() - p0.getY()); 
     return Math.sqrt(xdiff * xdiff + ydiff * ydiff); 
    } 

    private final Doctor doctor; 
    private final double distance; 
    private final String rep; 

    public DoctorDistance(Doctor doctor, double distance) { 
     if (doctor == null) { 
      throw new IllegalArgumentException(Doctor.NULL_ARG); 
     } 
     this.doctor = doctor; 
     this.distance = distance; 
     assert this.doctor != null; 

     rep = String.format(REP_FORMAT, doctor, distance); 
    } 

    public Doctor getDoctor() { 
     assert this.doctor != null; 
     return doctor; 
    } 

    public double getDistance() { 
     return distance; 
    } 

    @Override 
    public int hashCode() { 
     return doctor.hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (this == obj) { 
      return true; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final DoctorDistance other = (DoctorDistance) obj; 
     return this.doctor.equals(other.doctor); 
    } 

    @Override 
    public String toString() { 
     return rep; 
    } 
} 

и

package practice; 

import java.awt.Point; 
import java.util.Comparator; 
import java.util.SortedMap; 
import java.util.TreeMap; 

import static practice.DoctorDistance.metric; 

public class Doctor { 
    public static final String NULL_ARG = "Null argument"; 

    private static class Distancer implements Comparator<DoctorDistance> { 
     @Override 
     public int compare(DoctorDistance ddOne, DoctorDistance ddOther) { 
      return ddOne.equals(ddOther) ? 0 
        : ddOne.getDistance() < ddOther.getDistance() ? -1 
        : ddOne.getDistance() > ddOther.getDistance() ? 1 
        : 0; 
     } 
    } 

    private final SortedMap<DoctorDistance, DoctorDistance> distances = 
      new TreeMap<>(new Distancer()); 

    private final String name; 
    private final Point location; 
    private final String rep; 

    public Doctor(String name, Point location) { 
     if (name == null || location == null) { 
      throw new IllegalArgumentException(NULL_ARG); 
     } 
     this.name = name; 
     this.location = location; 
     assert this.name != null && this.location != null; 

     this.rep = '{' + this.name + ", (" + this.location.toString() + ')'; 
    } 

    public String getName() { 
     assert name != null; 
     return name; 
    } 

    public Point getLocation() { 
     assert location != null; 
     return location; 
    } 

    @Override 
    public int hashCode() { 
     return name.hashCode(); 
    } 

    @Override 
    public boolean equals(Object oth) { 
     if (oth == null) { 
      return false; 
     } 
     if (this == oth) { 
      return true; 
     } 
     if (getClass() != oth.getClass()) { 
      return false; 
     } 
     final Doctor other = (Doctor) oth; 
     return this.name.equals(other.name); 
    } 

    @Override 
    public String toString() { 
     return rep; 
    } 

    public DoctorDistance add(Doctor doctor) { 
     if (doctor == null) { 
      throw new IllegalArgumentException(NULL_ARG); 
     } 
     final DoctorDistance distance = new DoctorDistance(
       doctor, 
       metric(doctor.getLocation(), location)); 
     return distances.put(distance, distance); 
    } 

    public DoctorDistance getDistance(Doctor doctor) { 
     final DoctorDistance distance = new DoctorDistance(doctor, 0.0); 
     return distances.get(distance); 
    } 
} 

(Javadocs опущены для краткости)

+0

Спасибо, Лью. Это был первый раз, когда я пытался работать с универсальным методом и модифицировал его из того, что я нашел в Интернете. Понятно, что это лучший способ сделать это. – RajveerParikh