2015-12-29 5 views
8

मैं अपने आप को Collectors.toMap का एक प्रकार है जो एक ImmutableMap देता है, चाहने लगता है इस तरह के मैं ऐसा कर सकते हैं:जावा - क्या कोई स्ट्रीम कलेक्टर है जो ImmutableMap लौटाता है?

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

(जहां इस विशिष्ट उदाहरण में tuple एक स्काला Tuple2 है) मैं just learned है कि इस तरह के गुवा 21 (याय!) में जावा -8 समर्थन के साथ एक विधि आ रही है लेकिन यह 6 महीने दूर अच्छी लगती है। क्या किसी को मौजूदा पुस्तकालयों (आदि) के बारे में पता है जो आज इसे लागू कर सकता है?

ImmutableMap सख्ती से जरूरी नहीं है लेकिन मुझे सबसे अच्छा विकल्प लगता है: कुंजी द्वारा लुकअप, और मूल पुनरावृत्ति आदेश को बनाए रखना। अपरिवर्तनीयता हमेशा भी पसंद किया जाता है।

ध्यान दें कि FluentIterable.toMap(Function) पर्याप्त नहीं है क्योंकि मुझे एक कुंजी-मैपिंग फ़ंक्शन के साथ-साथ मूल्य-मैपिंग फ़ंक्शन दोनों की आवश्यकता है।

+1

मुझे आश्चर्य है कि आपने इंटरनेट पर कुछ भी नहीं देखा है। एक लोकप्रिय खोज इंजन में "अमरूद जावा 8 कलेक्टर" खोजना बहुत सीधे उपयोग करने योग्य कोड देता है, जिसमें सीधे अमरूद परियोजनाओं (मुद्दों के रूप में) में परिणाम शामिल हैं। –

+1

हमने इस उद्देश्य के लिए 'संग्रह और फिर()' प्रदान किया। –

+0

'ImmutableMultimap' पर प्रश्न में उत्तर वास्तव में मेरे तत्काल प्रश्नों का उत्तर देते हैं। हालांकि, वहां मौजूद समाधानों में से कोई भी नहीं है या जिसे मैंने वेब के आसपास पाया है, में 'इमटेबल मैप' को संभालने के लिए फ़ंक्शंस का एकदम सही सेट शामिल है - उनमें मर्ज-डुप्लिकेट-चाबियां और/या 'अवैध आधार अपवाद' को फेंकने की क्षमता नहीं है ('संग्राहक 'द्वारा निर्धारित सम्मेलन के बाद) –

उत्तर

13

आपको इस कलेक्टर के लिए अज्ञात कक्षा लिखने की आवश्यकता नहीं है। आप 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); 
} 

या यदि आप पहले एक परिवर्तनशील नक्शे में परिणाम एकत्रित कोई आपत्ति नहीं है और फिर एक अपरिवर्तनीय नक्शे में डेटा की प्रतिलिपि, आप collectingAndThen साथ निर्मित toMap कलेक्टर संयुक्त उपयोग कर सकते हैं :

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

बिल्कुल सही :-) मैंने इंटरफ़ेस को स्वयं ही देखना नहीं सोचा था। मैं निश्चित रूप से 'Collector.of' रूप को प्राथमिकता देता हूं क्योंकि यह अज्ञात भविष्य के उपयोग के साथ एक उपयोगिता कार्य बन जाएगा (और स्मृति मंथन के स्रोतों को ट्रैक करना बाद में मुश्किल हो सकता है।) –

+1

गुवा अब अपने संग्रह प्रकारों के लिए संग्राहक प्रदान करता है, उदा। [ 'ImmutableList.toImmutableMap()'] (https://github.com/google/guava/blob/2909a996047e575cdac02ea1c06a93a9419271cf/guava/src/com/google/common/collect/ImmutableMap.java#L65-L82)। – Jonathan

0

चूंकि मुझे अभी तक कलेक्टरों की ऐसी लाइब्रेरी नहीं मिली है, इसलिए मैं अपनी पहली क्रैक को उस विशिष्ट स्थान पर साझा कर रहा हूं जिसकी मुझे आवश्यकता है। यहां कोई घंटी या सीटी नहीं है! (जैसे डुप्लिकेट कुंजी को संभालना या विलय करना।)

कृपया सुधार का सुझाव देने में संकोच न करें।

/** 
* 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(); 
     } 
    }; 
} 
संबंधित मुद्दे