2015-12-29 21 views
8

tôi thấy mình muốn một biến thể của Collectors.toMap mà trả về một ImmutableMap, như vậy mà tôi có thể làm:Java - Có bất kỳ Trình thu thập luồng nào trả về ImmutableMap không?

ImmutableMap result = list.stream().collect(MyCollectors.toImmutableMap(
    tuple -> tuple._1(), tuple -> tuple._2()); 

(nơi tuple trong ví dụ đặc biệt này là một Scala Tuple2)

Tôi đã just learned rằng đó một phương pháp sẽ đến với sự hỗ trợ Java-8 trong Guava 21 (yay!) nhưng điều đó nghe có vẻ tốt 6 tháng. Có ai biết về bất kỳ thư viện hiện có (vv) mà có thể thực hiện điều này ngày hôm nay?

ImmutableMap không được yêu cầu nghiêm ngặt nhưng có vẻ là lựa chọn tốt nhất theo yêu cầu của tôi: tra cứu theo khóa và giữ lại thứ tự lặp gốc. Tính bất biến luôn được ưa thích.

Lưu ý rằng FluentIterable.toMap(Function) là không đủ vì tôi cần cả chức năng ánh xạ khóa cũng như hàm ánh xạ giá trị.

+1

Tôi rất ngạc nhiên khi bạn không thấy bất cứ điều gì trên internet. Tìm kiếm "guava java 8 collector" trong một công cụ tìm kiếm phổ biến trả về rất nhiều mã có thể sử dụng trực tiếp, bao gồm các kết quả trực tiếp trong các dự án ổi (như các vấn đề). –

+1

Chúng tôi cung cấp 'collectionsAndThen()' cho mục đích này. –

+0

Các câu trả lời trong câu hỏi trên 'ImmutableMultimap' thực sự trả lời các câu hỏi trước mắt của tôi. Tuy nhiên không có giải pháp nào ở đó hoặc bây giờ tôi tìm thấy trên web dường như chứa một tập hợp các hàm hoàn chỉnh để xử lý 'ImmutableMap' - chúng thiếu khả năng hợp nhất-khóa-phím và/hoặc không ném' IllegalStateException' (theo quy ước được thiết lập bởi 'Người sưu tầm') –

Trả lời

13

Bạn không cần phải viết một lớp ẩn danh cho người thu thập này. Bạn có thể sử dụng thay vì Collector.of:

public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
      Function<? super T, ? extends K> keyMapper, 
      Function<? super T, ? extends V> valueMapper) { 
    return Collector.of(
       ImmutableMap.Builder<K, V>::new, 
       (b, e) -> b.put(keyMapper.apply(e), valueMapper.apply(e)), 
       (b1, b2) -> b1.putAll(b2.build()), 
       ImmutableMap.Builder::build); 
} 

Hoặc nếu bạn không nhớ thu thập kết quả thành một bản đồ có thể thay đổi đầu tiên và sau đó sao chép dữ liệu vào một bản đồ bất biến, bạn có thể sử dụng được xây dựng trong toMap sưu tập kết hợp với collectingAndThen :

ImmutableMap<String, String> result = 
    list.stream() 
     .collect(collectingAndThen(
      toMap(
       tuple -> tuple._1(), 
       tuple -> tuple._2()), 
      ImmutableMap::copyOf)); 
+1

Hoàn hảo :-) Tôi không nghĩ rằng để nhìn vào giao diện chính nó. Tôi chắc chắn thích hình thức 'Collector.of' vì điều này sẽ trở thành một chức năng tiện ích với việc sử dụng không rõ trong tương lai (và theo dõi các nguồn dữ liệu của bộ nhớ có thể khó sau này.) –

+1

Hiện tại, Guava cung cấp các bộ sưu tập cho các loại bộ sưu tập của họ. ['ImmutableList.toImmutableMap()'] (https://github.com/google/guava/blob/2909a996047e575cdac02ea1c06a93a9419271cf/guava/src/com/google/common/collect/ImmutableMap.java#L65-L82). – Jonathan

0

Vì tôi chưa tìm thấy một thư viện thu thập như vậy, tôi đang chia sẻ vết nứt đầu tiên của mình tại một nơi cụ thể mà tôi cần. Không có chuông hay còi ở đây! (Chẳng hạn như xử lý hoặc hợp nhất các khóa trùng lặp.)

Vui lòng đề xuất cải tiến.

/** 
* A variant of {@link Collectors#toMap(Function, Function)} for immutable maps. 
* <p> 
* Note this variant throws {@link IllegalArgumentException} upon duplicate keys, rather than 
* {@link IllegalStateException} 
* 
* @param <T> type of the input elements 
* @param <K> output type of the key mapping function 
* @param <V> output type of the value mapping function 
* @param keyMapper a mapping function to produce keys 
* @param valueMapper a mapping function to produce values 
* 
* @return a {@code Collector} which collects elements into a {@code Map} whose keys and values 
*   are the result of applying mapping functions to the input elements 
*   
* @throws IllegalArgumentException upon duplicate keys 
*/ 
public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
     Function<? super T, ? extends K> keyMapper, 
     Function<? super T, ? extends V> valueMapper) { 
    return new Collector<T, ImmutableMap.Builder<K,V>, ImmutableMap<K,V>>() { 

     public Supplier<Builder<K, V>> supplier() { 
      return ImmutableMap.Builder::new; 
     } 

     public BiConsumer<Builder<K, V>, T> accumulator() { 
      return (builder, element) -> { 
       K key = keyMapper.apply(element); 
       V value = valueMapper.apply(element); 
       builder.put(key, value); 
      }; 
     } 

     public BinaryOperator<Builder<K, V>> combiner() { 
      return (b1, b2) -> { 
       b1.putAll(b2.build()); 
       return b1; 
      }; 
     } 

     public Function<Builder<K, V>, ImmutableMap<K, V>> finisher() { 
      return builder -> builder.build(); 
     } 

     public Set<Collector.Characteristics> characteristics() { 
      return ImmutableSet.of(); 
     } 
    }; 
} 
Các vấn đề liên quan