2017-12-14 99 views
7

Giả sử tôi có một danh sách chứa công nhân, mỗi người lao động có 3 lĩnh vực: tên của nó, bộ phận anh ta làm việc (có thể chỉ là tên của bộ phận hoặc một Object từ Sở lớp) và lương của anh ấy.Làm thế nào để sắp xếp các chuỗi trùng lặp bằng cách sử dụng bộ so sánh?

Elvis  Software Engineering  1000 
Samba  Mechanical Engineering  2000 
Bamba  Industrial Engineering  3000 
Bisli  Medical Engineering   4000 
Kinder  Electrical Engineering  1000 
Elvis  Software Engineering  9999 

bây giờ tôi muốn sắp xếp chúng theo tên của chúng và đặt kết quả vào Hàng đợi. và hơn đặt hàng đợi trong một bản đồ, đặt hàng từ phía dưới lên đỉnh vì vậy kết quả tôi mong muốn sau khi loại là:

Bamba  Industrial Engineering  3000 
Bisli  Medical Engineering   4000 
Elvis  Software Engineering  1000 
Elvis  Software Engineering  9999 
Samba  Mechanical Engineering  2000 
Kinder  Electrical Engineering  1000 

Tôi không được phép sử dụng Collection.sort(), vì vậy tôi bằng cách sử dụng một bộ so sánh phân loại các công nhân theo tên của họ, nếu tên là như nhau - nó sắp xếp theo bộ phận, nếu bộ phận là bình đẳng - nó sắp xếp theo mức lương. đây là so sánh tôi đã viết:

class WorkerComparatorByName implements Comparator<Worker<?>> { 
    @Override 
    public int compare(Worker<?> w1, Worker<?> w2) { 
     int compareValue = w1.getName().compareTo(w2.getName()); 
     if (compareValue != 0) 
      return compareValue; 
     compareValue = w1.getDepartment().toString().compareTo(w2.getDepartment().toString()); 
     if (compareValue != 0) 
      return compareValue; 
     return w1.getSalary() - w2.getSalary(); 

    } 
} 

vấn đề là kết quả là thế này:

Bamba  Industrial Engineering  3000 
Bisli  Medical Engineering   4000 
Elvis  Software Engineering  1000 
Samba  Mechanical Engineering  2000 
Kinder  Electrical Engineering  1000 
Elvis  Software Engineering  9999 

tất cả người lao động đều được sắp xếp, nhưng Elvis (được nhân đôi) là không được sắp xếp, nó sẽ nằm tại cuối hàng đợi. Tôi đã thử thay thế Elvis bằng một tên trùng lặp khác và cùng một kết quả. Tôi đang thiếu gì? làm thế nào tôi có thể sắp xếp giá trị trùng lặp để họ sẽ là một sau khi khác? Dưới đây là các mã:

public <T extends Worker<?>> Map<?, ?> createMap(ArrayList<T> list) { 
    int i = 1; 
    // creating a PriorityQueue sorted by names 
    Queue<T> pq = new PriorityQueue<>(new WorkerComparatorByName()); 
    // filling the PriorityQueue with the workers 
    pq.addAll(list); 
    Map<Integer, T> treeMap = new TreeMap<Integer, T>(); 
    // iterating over the PriorityQueue and puting the workers in the map 
    for (T element : pq) 
     treeMap.put(i++, element); 
    return treeMap; 
} 
+0

Tại sao bạn sử dụng PriorityQueue? Nếu bạn muốn cấu trúc dữ liệu sắp xếp các phần tử cho bạn bằng cách sử dụng Comparator đó, hãy sử dụng 'TreeSet'. – Eran

+0

Lớp này và trình lặp của nó thực hiện tất cả các phương thức tùy chọn của giao diện Bộ sưu tập và Iterator. Iterator được cung cấp trong phương thức iterator() không được bảo đảm để duyệt qua các phần tử của hàng đợi ưu tiên theo bất kỳ thứ tự cụ thể nào. Nếu bạn cần traversal theo thứ tự, hãy xem xét sử dụng Arrays.sort (pq.toArray()). Tham khảo tài liệu: https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html –

Trả lời

2

PriorityQueue API:

Các Iterator cung cấp trong phương pháp lặp() không được bảo đảm để đi qua các phần tử của hàng đợi ưu tiên trong bất kỳ thứ tự cụ thể. Nếu bạn cần traversal theo thứ tự, hãy xem xét sử dụng Arrays.sort (pq.toArray()).

1

Thay vì sử dụng vòng lặp foreach, hãy sử dụng vòng lặp for bình thường và poll() các mục từ hàng đợi.

// creating a PriorityQueue sorted by names 
Queue<T> pq = new PriorityQueue<>(new WorkerComparatorByName()); 

// filling the PriorityQueue with the workers 
pq.addAll(list); 

Map<Integer, T> treeMap = new TreeMap<Integer, T>(); 

int size = pq.size(); 
for (int j = 0; j < size; j++) { 
     treeMap.put(j + 1, pq.poll()); 
} 
+0

cảm ơn tất cả mọi người, tôi đã sử dụng TreeSet và được định nghĩa trong bộ so sánh rằng nếu người lao động giống nhau, xem xét một trong số chúng lớn hơn. – Robert

0

Sử dụng câu hỏi này làm bài tập trực tuyến/lambda, cũng đã sử dụng một số tiện ích Java 8 comparing. Thấy rằng bạn đã kết thúc bằng cách sử dụng một TreeSet, đó là một giải pháp tốt, nhưng tôi sẽ bổ sung thêm điều này nếu có ai đó quan tâm.

PriorityQueue<Worker> queue = 
     new PriorityQueue<>(Comparator.comparing(Worker::getName) 
            .thenComparing(Worker::getDepartment) 
            .thenComparing(Worker::getSalary)); 
queue.addAll(list); 

TreeMap<Integer, Worker> treeMap = 
     IntStream.range(1, queue.size() + 1) 
       .boxed() 
       .collect(Collectors.toMap(Function.identity(), 
              o -> queue.poll(), 
              (u, v) -> { throw new Error("Will never happen"); }, 
              TreeMap::new)); 
Các vấn đề liên quan