2009-04-13 20 views
24

मैं जावा संग्रह में एक फ़ंक्शन लागू करना चाहता हूं, इस विशेष मामले में एक मानचित्र। क्या ऐसा करने का कोई अच्छा तरीका है? मेरे पास एक नक्शा है और मानचित्र में सभी मूल्यों पर ट्रिम() को चलाने के लिए और मानचित्र को अपडेट को प्रतिबिंबित करना चाहते हैं।जावा संग्रह/मानचित्र लागू विधि के बराबर है?

उत्तर

36
जावा 8 के lambdas के साथ

, यह एक एक लाइनर है:

public void trimValues(Map<?, String> map) { 
    for (Map.Entry<?, String> e : map.entrySet()) { 
    String val = e.getValue(); 
    if (val != null) 
     e.setValue(val.trim()); 
    } 
} 

या, अधिक आम तौर पर:

interface Function<T> { 
    T operate(T val); 
} 

public static <T> void replaceValues(Map<?, T> map, Function<T> f) 
{ 
    for (Map.Entry<?, T> e : map.entrySet()) 
    e.setValue(f.operate(e.getValue())); 
} 

Util.replaceValues(myMap, new Function<String>() { 
    public String operate(String val) 
    { 
    return (val == null) ? null : val.trim(); 
    } 
}); 

map.replaceAll((k, v) -> v.trim()); 

इतिहास के लिए, यहाँ lambdas के बिना एक संस्करण है

+1

+1 टेम्पलेट लैम्ब्डा फ़ंक्शन – Alnitak

+0

अरे एरिक्सन - मैं इस वाक्यविन्यास के बारे में कहां से सीख सकता हूं: मानचित्र मानचित्र ?? मैं सिर्फ जावा सीख रहा हूं और ऐसा कुछ भी नहीं आया है .. किसी भी दिशा की सराहना की जाएगी! –

+2

@jamesemanon इसका मतलब है कि जिस विधि को आप इस विधि में पास करते हैं, उसके पास किसी भी प्रकार की कुंजी हो सकती है, लेकिन मान 'स्ट्रिंग' होना चाहिए। आप [जावा ट्यूटोरियल] (https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html) से मूल बातें प्राप्त कर सकते हैं। [एंजेलिका लैंगर के सामान्य प्रश्न] [http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html) जावा जेनरिक के सभी पहलुओं के बारे में अधिक विस्तृत जानकारी है। – erickson

2

चाहे आप अपने संग्रह को संशोधित कर सकें या नहीं, संग्रह में वस्तुओं की कक्षा पर निर्भर करता है।

यदि वे वस्तुएं अपरिवर्तनीय हैं (जो स्ट्रिंग्स हैं) तो आप संग्रह से आइटम नहीं ले सकते हैं और उन्हें संशोधित नहीं कर सकते हैं - इसके बजाय आपको संग्रह पर पुन: सक्रिय करने की आवश्यकता होगी, प्रासंगिक फ़ंक्शन को कॉल करें, और उसके बाद परिणामस्वरूप मूल्य वापस।

1

आपको सभी प्रविष्टियों पर फिर से शुरू करना होगा और प्रत्येक स्ट्रिंग मान को ट्रिम करना होगा। चूंकि स्ट्रिंग अपरिवर्तनीय है, इसलिए आपको इसे मानचित्र में फिर से रखना होगा। वैल्यू को ट्रिम करने के लिए एक बेहतर तरीका हो सकता है क्योंकि वे मानचित्र में रखे गए हैं।

2

इस तरह के कुछ के लिए ओवरकिल हो सकता है, लेकिन Apache Commons Collections लाइब्रेरी में इन प्रकार की समस्याओं के लिए कई वास्तव में अच्छी सुविधाएं हैं।

Map<String, String> map = new HashMap<String, String>(); 
map.put("key1", "a "); 
map.put("key2", " b "); 
map.put("key3", " c"); 

TransformedMap.decorateTransform(map, 
    TransformerUtils.nopTransformer(), 
    TransformerUtils.invokerTransformer("trim")); 

मैं ओ'रेली से Jakarta Commons Cookbook की अत्यधिक अनुशंसा करता हूं।

+1

बस अपाचे कॉमन्स कलेक्शन लाइब्रेरी में अपरिवर्तनीय संस्करण का उल्लेख करना चाहता था: संग्रहUtils.collect (संग्रह इनपुट चयन, ट्रांसफार्मर ट्रांसफॉर्मर) – Jakub

-1

आप Google संग्रह पर एक नज़र

+2

अस्पष्टता की तरह ... कम से कम एक लिंक और Google संग्रह का उपयोग करने का विवरण/उदाहरण प्रदान करें समस्या का समाधान? –

11

मुझे लगता है कि JDK लाइब्रेरी को अपने स्वीकार किए जाते हैं प्रतिक्रिया के अलावा अन्य के साथ, फिर भी गूगल संग्रह से आपको वर्गों के साथ है, तो निम्न बात करने की सुविधा देता करने के लिए एक तरह से पता नहीं है ले सकता है com.google.collect.Maps और com.google.common.base.Function:

Map<?,String> trimmedMap = Maps.transformValues(untrimmedMap, new Function<String, String>() { 
    public String apply(String from) { 
    if (from != null) 
     return from.trim(); 
    return null; 
    } 
} 

प्रस्तावित एक के साथ कि विधि का सबसे बड़ा अंतर यह है कि यह, अपने मूल नक्शा, इसका मतलब है कि जो करने के लिए एक दृश्य प्रदान करता है सिंक में हमेशा होता है, जबकि यह अपने मूल नक्शे के साथ, apply विधि है यदि आप साई में हेरफेर कर रहे हैं तो कई बार बुलाया जा सकता है डी मानचित्र भारी।

संग्रह के लिए समान Collections2.transform(Collection<F>,Function<F,T>) विधि मौजूद है।

1

मैं एक "मैपर" वर्ग के साथ आए हैं

public static abstract class Mapper<FromClass, ToClass> { 

    private Collection<FromClass> source; 

    // Mapping methods 
    public abstract ToClass map(FromClass source); 

    // Constructors 
    public Mapper(Collection<FromClass> source) { 
     this.source = source; 
    } 
    public Mapper(FromClass ... source) { 
     this.source = Arrays.asList(source); 
    } 

    // Apply map on every item 
    public Collection<ToClass> apply() { 
     ArrayList<ToClass> result = new ArrayList<ToClass>(); 
     for (FromClass item : this.source) { 
      result.add(this.map(item)); 
     } 
     return result; 
    } 
} 

मैं उस तरह उपयोग करते हैं:

Collection<Loader> loaders = new Mapper<File, Loader>(files) { 
    @Override public Loader map(File source) { 
     return new Loader(source); 
    }   
}.apply(); 
2

मैं @ एरिक्सन के जवाब का उत्परिवर्तन, करने के लिए उत्परिवर्तित का उपयोग कर समाप्त हो गया:

  • एक नया Collection लौटाएं, जगह
  • में संशोधित नहीं करें वापसी प्रकार के तत्वों या तो एक नक्शा के मूल्यों या एक सूची

संहिता के तत्वों से अधिक Function

  • समर्थन मानचित्रण की वापसी प्रकार के बराबर के साथ Collection रों: के लिए

    public static interface Function<L, R> { 
        L operate(R val); 
    } 
    
    public static <K, L, R> Map<K, L> map(Map<K, R> map, Function<L, R> f) { 
        Map<K, L> retMap = new HashMap<K, L>(); 
    
        for (Map.Entry<K, R> e : map.entrySet()) retMap.put(e.getKey(), f.operate(e.getValue())); 
    
        return retMap; 
    } 
    
    public static <L, R> List<L> map(List<R> list, Function<L, R> f) { 
        List<L> retList = new ArrayList<L>(); 
    
        for (R e : list) retList.add(f.operate(e)); 
    
        return retList; 
    } 
    
  • संबंधित मुद्दे