2015-04-25 38 views

Trả lời

0

Kể từ Java 1,8 java.util.Comparator.reversed()

myMap.entrySet().stream() 
.sorted(Map.Entry.comparingByValue().reversed()) 
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 
5

Bạn có thể chuyển bất kỳ Bộ so sánh nào bạn muốn comparingByValue.

Ví dụ (Tôi hy vọng tôi có đúng cú pháp, vì tôi không thể kiểm tra nó):

myMap.entrySet().stream() 
    .sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1))) 
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 

Bằng cách so sánh giá trị của hai mục theo thứ tự ngược lại, sử dụng thứ tự tự nhiên (Comparable 's compareTo), bạn nhận được một đơn đặt hàng đảo ngược so với những gì comparingByValue() (tương đương với comparingByValue((v1,v2)->v1.compareTo(v2))) sẽ cung cấp cho bạn.

BTW, tôi không chắc chắn rằng Collectors.toMap trả về phiên bản LinkedHashMap và ngay cả khi hiện tại, nó có thể thay đổi trong tương lai, vì Javadoc không đề cập đến nó, vì vậy bạn không thể dựa vào nó.

Để chắc chắn rằng bản đồ kết quả sẽ là một LinkedHashMap, bạn nên sử dụng một biến thể khác nhau của toMap:

myMap.entrySet().stream() 
    .sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1))) 
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1,v2)->v1, LinkedHashMap::new)); 
+1

Như tên gọi của nó chỉ ra ('comparingByValue'), các thông số kiểu của biểu thức lambda là 'V' không' nhập cảnh 'vì bạn cung cấp một bộ so sánh trên các giá trị, vì vậy bạn có thể thay đổi nó thành' compareByValue ((v1, v2) -> v2.compareTo (v1)) 'hoặc sử dụng tốt hơn' compareByValue (reverseOrder()) 'như @Misha được đề xuất ... –

+0

..và khi bạn nói một cách nhanh chóng xem mã nguồn của 'toMap' bạn sẽ thấy rằng nó trả về' toMap (keyMapper, valueMapper, throwingMerger(), HashMap :: new); '. Vì vậy, về cơ bản thực hiện của bạn sẽ không làm điều gì đó rất hữu ích (mặc dù bạn đã lấy nó từ câu hỏi của OP) ... –

+1

@AlexisC. Cảm ơn bạn đã bình luận. Tôi hoàn toàn bỏ lỡ điều đó. Đó là những gì xảy ra khi tôi viết mã mà không cố gắng biên dịch nó. – Eran

25

Để sắp xếp theo thứ tự đảo ngược, vượt qua Comparator.reverseOrder() như tham số để comparingByValue.

Để nhận được LinkedHashMap, bạn phải yêu cầu cụ thể một đối số có 4 đối số toMap(). Nếu bạn không chỉ định loại bản đồ bạn muốn, bạn sẽ nhận được bất kỳ giá trị mặc định nào, hiện đang xảy ra là HashMap. Vì HashMap không giữ nguyên thứ tự của các phần tử, nó chắc chắn sẽ không làm cho bạn.

myMap.entrySet().stream() 
     .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 
     .collect(Collectors.toMap(
       Map.Entry::getKey, 
       Map.Entry::getValue, 
       (x,y)-> {throw new AssertionError();}, 
       LinkedHashMap::new 
     )); 

Với nhập khẩu tĩnh, nó trở nên dễ chịu hơn một chút:

myMap.entrySet().stream() 
     .sorted(comparingByValue(reverseOrder())) 
     .collect(toMap(
       Map.Entry::getKey, 
       Map.Entry::getValue, 
       (x,y)-> {throw new AssertionError();}, 
       LinkedHashMap::new 
     )); 
+0

Câu trả lời này là câu trả lời hợp lệ duy nhất. –

+0

Cảm ơn, tôi không biết rằng tôi có thể sử dụng Comparator.reverserOrder() này. Trong thực tế, tôi nghĩ rằng sẽ tồn tại một cách trực tiếp để làm điều này, như .sorted (Map.Entry.comparingByValueReverse()) – Oxydron

3

Stream có như sorted phương pháp mà chấp nhận một so sánh do đó bạn có thể trực tiếp sử dụng so sánh như (x,y)->y.getKey().compareTo(x.getKey()) cho giảm dần phân loại. Để sắp xếp các đồ tăng dần chúng ta có thể đảo ngược thứ tự như (x,y)->x.getKey().compareTo(y.getKey())

cho việc củng cố kết quả trở lại vào LinkedHashMap chúng ta có thể sử dụng thu gom toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) mà Trả về một Collector mà tích tụ các yếu tố vào một bản đồ có khóa và giá trị là kết quả của việc áp dụng cung cấp chức năng lập bản đồ cho các yếu tố đầu vào.

đang làm việc

import java.io.*; 
import java.util.*; 
import java.util.function.*; 
import java.util.stream.Collectors; 
import java.util.stream.*; 
public class HelloWorld{ 

    public static void main(String []args){ 
     LinkedHashMap<Integer,Integer> hashMap = new LinkedHashMap<Integer,Integer>(); 
      hashMap.put(1,5); 
      hashMap.put(7,9); 
      hashMap.put(3,8); 
      hashMap.put(10,5); 

      Function<Map.Entry<Integer,Integer>,Integer> keyMapper = x->x.getKey(); 
      Function<Map.Entry<Integer,Integer>,Integer> valueMapper = x->x.getValue(); 
      BinaryOperator< Integer> mergeFunction = (x,y)->x;// we do not want any merging here 
      Supplier<LinkedHashMap<Integer,Integer>> mapRequired =()-> {return new LinkedHashMap<Integer,Integer>();};// to maintain order we must use LinkedHashMap 
      Comparator<Map.Entry<Integer,Integer>> descendingComparator = (x,y)->y.getKey().compareTo(x.getKey()); 
      // we can write it as 

     System.out.println(
        hashMap.entrySet().stream() 
          .sorted (descendingComparator) 
          .collect(Collectors.toMap(
                 keyMapper, 
                 valueMapper, 
                 mergeFunction, 
                 mapRequired) 
              ) 
       );   

// or even by writing below will also work 

     System.out.println(
        hashMap.entrySet().stream() 
          .sorted ((x,y)->y.getKey().compareTo(x.getKey())) 
          .collect(Collectors.toMap(
                 x->x.getKey(), 
                 x->x.getValue(), 
                 (x,y)->x, 
                 LinkedHashMap::new) 
              ) 
       );   
    } 


} 
Các vấn đề liên quan