2015-09-20 20 views
8

Sửa :: Tôi rephrasing câu hỏi để nó rõ ràng hơnJava 8 Streams - Phân nhóm một dòng tuples

Tôi đã viết mã này

List<ImmutablePair<Integer, Integer>> list = new ArrayList<ImmutablePair<Integer, Integer>>(); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(3, 3)); 
    list.add(new ImmutablePair(3, 3)); 
    list.add(new ImmutablePair(3, 3)); 
    Stream<ImmutablePair<Integer, Integer>> stream = list.stream(); 
    Map<Integer, Integer> result = stream.collect(Collectors.groupingBy(
     ImmutablePair::getLeft, 
      Collectors.mapping(
        ImmutablePair::getRight, 
        Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight)) 
      )     
    )); 

Tôi muốn để xử lý danh sách này sử dụng hơi nước để rằng đầu ra là một bản đồ chứa các khóa (1, 3), (2, 6), (3, 9)

Vì vậy, về cơ bản, chúng tôi nhóm vào mục bên trái của bộ và sau đó tổng hợp mục bên phải.

Mã này không biên dịch và trình biên dịch nói rằng nó không thể giải quyết phương thức getLeft, getRight.

Dưới đây là các thông báo lỗi từ trình biên dịch

/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: method summingInt in class Collectors cannot be applied to given types; 
          Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight)) 
            ^
    required: ToIntFunction<? super T#1> 
    found: Comparator<Object> 
    reason: no instance(s) of type variable(s) T#2,U exist so that Comparator<T#2> conforms to ToIntFunction<? super T#1> 
    where T#1,T#2,U are type-variables: 
    T#1 extends Object declared in method <T#1>summingInt(ToIntFunction<? super T#1>) 
    T#2 extends Object declared in method <T#2,U>comparing(Function<? super T#2,? extends U>) 
    U extends Comparable<? super U> declared in method <T#2,U>comparing(Function<? super T#2,? extends U>) 
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: incompatible types: cannot infer type-variable(s) T,U 
          Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight)) 
                    ^
    (argument mismatch; invalid method reference 
     no suitable method found for getRight(Object) 
      method Pair.getRight() is not applicable 
      (actual and formal argument lists differ in length) 
      method ImmutablePair.getRight() is not applicable 
      (actual and formal argument lists differ in length)) 
    where T,U are type-variables: 
    T extends Object declared in method <T,U>comparing(Function<? super T,? extends U>) 
    U extends Comparable<? super U> declared in method <T,U>comparing(Function<? super T,? extends U>) 
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:229: error: invalid method reference 
          Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight)) 
                    ^
    non-static method getRight() cannot be referenced from a static context 
    where R is a type-variable: 
    R extends Object declared in class ImmutablePair 
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:228: error: invalid method reference 
          ImmutablePair::getRight, 
          ^
    non-static method getRight() cannot be referenced from a static context 
    where R is a type-variable: 
    R extends Object declared in class ImmutablePair 
/Users/abhi/JavaProjects/MovieLambda2/src/main/java/com/abhi/MovieLambda2.java:226: error: invalid method reference 
        ImmutablePair::getLeft, 
        ^
    non-static method getLeft() cannot be referenced from a static context 
    where L is a type-variable: 
    L extends Object declared in class ImmutablePair 
+3

Bạn nên đăng một ví dụ đơn giản trình bày vấn đề, nếu không chúng tôi sẽ khó tái tạo nó. – Tunaki

+1

Còn về Collectors.groupBy (ImmutablePair :: getLeft) thì sao? Ý tôi là riêng biệt. Liệu nó cũng thất bại? –

+2

Bạn đang cố gắng nhóm các trường hợp của ImmutablePair bằng cách sử dụng tham chiếu đến một phương thức của Phim. Điều đó không thể hoạt động được. Điều đó giống như phân loại người bởi màu của quả chuối. Bạn có thể sắp xếp mọi người theo chiều cao hoặc cân nặng của họ hoặc tuổi của họ, nhưng không phải bởi một tài sản của một quả chuối. Chúng tôi có thể giải thích thông báo lỗi chính xác có nghĩa là gì nếu bạn đăng thông báo lỗi chính xác thay vì diễn giải nó và đưa ra sự hiểu biết của bạn về thông điệp không chính xác. Chúng tôi có thể giúp bạn sửa mã nếu bạn đăng các lớp học liên quan. –

Trả lời

4

Cập nhật: này trả lời một câu hỏi ban đầu (revision 2). Câu hỏi mới cũng được trả lời bởi @ Shiraaz.M.


bạn Comparator chấp nhận một cặp, do đó bạn cần phải gọi getRight với Collectors.mapping:

Map<String, Optional<Movie>> map = ml.getDataAsStream() 
    .<ImmutablePair<String, Movie>>flatMap(x -> x.getGenre() 
      .map(g -> new ImmutablePair<String, Movie>(g, x))) 
    .collect(
      Collectors.groupingBy(
       ImmutablePair::getLeft, 
       Collectors.mapping(ImmutablePair::getRight, 
        Collectors.maxBy(Comparator.comparing(Movie::getVoteCount))) 
      )); 

Lưu ý rằng tùy thuộc vào trình biên dịch sử dụng bạn có thể cần phải xác định một số loại một cách rõ ràng như tự động suy luận có thể thất bại.

Thực tế các tình huống đó được hỗ trợ tốt trong thư viện StreamEx của tôi để tăng cường các luồng Java chuẩn. Cùng một kết quả có thể đạt được bằng văn bản này:

Map<String, Optional<Movie>> map = StreamEx.of(ml.getDataAsStream()) 
    .cross(Movie::getGenre) // create (Movie, Genre) entries 
    .invert() // swap entries to get (Genre, Movie) 
    .grouping(Collectors.maxBy(Comparator.comparing(Movie::getVoteCount))); 

Cuối cùng lưu ý rằng việc sử dụng maxBy thu bạn sẽ phải Optional giá trị đó là vô dụng khi họ không thể để trống.Đối với maxBy/minBy kịch bản nó tốt hơn để sử dụng toMap nhà sưu tập với chức năng tùy chỉnh sáp nhập:

Map<String, Movie> map = ml.getDataAsStream() 
    .<ImmutablePair<String, Movie>>flatMap(x -> x.getGenre() 
      .map(g -> new ImmutablePair<String, Movie>(g, x))) 
    .collect(Collectors.toMap(ImmutablePair::getLeft, ImmutablePair::getRight, 
      BinaryOperator.maxBy(Comparator.comparing(Movie::getVoteCount)))); 

Hoặc sử dụng StreamEx:

Map<String, Movie> map = StreamEx.of(ml.getDataAsStream()) 
    .cross(Movie::getGenre) 
    .invert() 
    .toMap(BinaryOperator.maxBy(Comparator.comparing(Movie::getVoteCount))); 
+0

Tôi nghĩ rằng ví dụ trước của tôi là một chút phức tạp. vì vậy tôi –

+0

Điều này không hoạt động. Tôi đã triển khai đề xuất ở trên. nhưng tôi vẫn nhận được thông báo trình biên dịch 'không thể giải quyết getLeft' –

+2

Không quan tâm, những gì invert() làm gì? –

6

Giả sử lớp ImmutablePair của bạn trông như thế này (lớp này có thể cần phải được tĩnh tuỳ thuộc vào việc mã mẫu được thực hiện từ bên trong một phương thức chính):

class ImmutablePair<T,T2> { 
    private final T left; 
    private final T2 right; 

    public ImmutablePair(T left, T2 right) { 
     this.left = left; 
     this.right = right; 

    } 

    public T getLeft() { 
     return left; 
    } 

    public T2 getRight() { 
     return right; 
    } 
} 

Điều này có vẻ phù hợp với tôi:

List<ImmutablePair<Integer, Integer>> list = new ArrayList<>(); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(1, 1)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(2, 2)); 
    list.add(new ImmutablePair(3, 3)); 
    list.add(new ImmutablePair(3, 3)); 
    list.add(new ImmutablePair(3, 3)); 
    Map<Integer, Integer> collect = list.stream() 
     .collect(
      Collectors.groupingBy(
       ImmutablePair::getLeft, 
       Collectors.summingInt(ImmutablePair::getRight))); 

    System.out.println(collect); 

Và kết quả là:

{1 = 3, 2 = 6, 3 = 9}

Vấn đề có thể

Vấn đề là ở phần này của mã:

 Collectors.mapping(
       ImmutablePair::getRight, 
       Collectors.summingInt(Comparator.comparing(ImmutablePair::getRight)) 
     ) 
.210

Các nhà sưu tập Collectors.mapping đầu tiên điều chỉnh một đối tượng kiểu T vào và đối tượng của loại U và sau đó chạy một nhà sưu tập trên loại U. (That's the gist of the javadoc for me)

Vì vậy, những gì bạn đang làm là một cái gì đó như:

  • Biến đổi thẻ không thể chuyển đổi thành số nguyên.
  • Tham số thứ 2 giờ đây là Bộ sưu tập có kiểu Integer, nhưng bạn đang "sử dụng loại ImmutablePair". Ngoài ra, Comparator.compare() trả về một Comparator và bạn đang tìm cách trả về một kiểu Integer. Vì vậy, để sửa chữa đường chính xác của bạn đang thay đổi nó thành một cái gì đó như:

Collectors.mapping (ImmutablePair :: GetRight, Collectors.summingInt (Integer :: valueOf))

Nhưng bạn không cần điều này vì bạn có thể đơn giản hóa này bằng cách gọi trực tiếp Collectors.summingInt:

Collectors.summingInt (ImmutablePair :: GetRight)

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