2010-03-07 27 views
11

मैं एक एडाप्टर फ्रेमवर्क लिख रहा हूं जहां मुझे वस्तुओं की सूची को एक वर्ग से दूसरे में परिवर्तित करने की आवश्यकता है। मैं के रूप मेंजावा: एक तत्व प्रकार की सूचियों को किसी अन्य प्रकार की सूची में परिवर्तित करना

Java: Best way of converting List<Integer> to List<String>

हालांकि, मैं अगर वहाँ जब लक्ष्य सूची दोहराया जा रहा है मक्खी पर यह करने के लिए एक रास्ता है सोच रहा हूँ यह करने के लिए स्रोत सूची के माध्यम से पुनरावृति कर सकते हैं, तो मैं डॉन ' सूची में दो बार पुन: प्रयास करना होगा।

उत्तर

0

यह प्रश्न दो बार सूची के माध्यम से पुन: सक्रिय नहीं होता है। यह सिर्फ एक बार फिर से शुरू होता है और अब तक एकमात्र ज्ञात विधि है।

इसके अलावा आप गूगल-संग्रह के कॉमन्स-संग्रह में कुछ ट्रांसफार्मर कक्षाएं इस्तेमाल कर सकते हैं लेकिन वे सभी हुड :) एक तरह से निम्नलिखित जा रहा है

CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer()); 
+0

सूची पुनरावृत्त नहीं है (कम से कम) दो बार; एक बार मूल सूची में जब रूपांतरण किया जाता है और फिर फिर जब लक्ष्य सूची को फिर से चालू किया जाता है? –

0

खैर के तहत एक ही बात करते हैं, आप अपने खुद के बना सकते हैं यह करने के लिए इटरेटर रैपर वर्ग। लेकिन मुझे संदेह है कि आप ऐसा करके बहुत बचत करेंगे।

यहां एक साधारण उदाहरण है जो मैपिंग करने के लिए ऑब्जेक्ट.toString() का उपयोग करके किसी भी इटरेटर को स्ट्रिंग इटरेटर पर लपेटता है।

public MyIterator implements Iterator<String> { 

    private Iterator<? extends Object> it; 

    public MyIterator(Iterator<? extends Object> it) { 
     this.it = it; 
    } 

    public boolean hasNext() { 
     return it.hasNext(); 
    } 

    public String next() { 
     return it.next().toString(); 
    } 

    public void remove() { 
     it.remove(); 
    } 
} 
2

आप एक मैपिंग इटरेटर लिख सकते हैं जो मौजूदा इटरेटर को सजाने और उस पर एक फ़ंक्शन लागू करता है। इस मामले में, फ़ंक्शन ऑब्जेक्ट्स को एक प्रकार से दूसरे "ऑन-द-फ्लाई" में बदल देता है।

कुछ इस तरह:

import java.util.*; 

abstract class Transformer<T, U> implements Iterable<U>, Iterator<U> { 
    public abstract U apply(T object); 

    final Iterator<T> source;  
    Transformer(Iterable<T> source) { this.source = source.iterator(); } 

    @Override public boolean hasNext() { return source.hasNext(); } 
    @Override public U next()   { return apply(source.next()); } 
    @Override public void remove()  { source.remove(); } 

    public Iterator<U> iterator()  { return this; } 
} 

public class TransformingIterator { 
    public static void main(String args[]) { 
     List<String> list = Arrays.asList("1", "2", "3"); 
     Iterable<Integer> it = new Transformer<String, Integer>(list) { 
      @Override public Integer apply(String s) { 
       return Integer.parseInt(s); 
      } 
     }; 
     for (int i : it) { 
      System.out.println(i); 
     } 
    } 
} 
+0

यह जो मैं ढूंढ रहा हूं उसके करीब दिखता है। इसी तरह की प्रतिक्रिया के अनुसार, फ्लाई पर ऐसा करने से मुझे बहुत फायदा होता है? –

+0

ईमानदारी से, मुझे लगता है कि Google संग्रह समाधान (बेन लिंग ') बेहतर हो सकता है। उनका डिजाइन बहुत अधिक परिपक्व है, और उनका कार्यान्वयन अधिक मजबूत है। सचमुच मैंने उस कोड को 15 मिनट में इतनी ज्यादा सोचने के बिना मार डाला। – polygenelubricants

+1

मेरा मतलब है, कक्षा 'Iterator ' और 'Iterable ' लागू करती है। मुझे यकीन नहीं है कि यह कोशेर है या नहीं। – polygenelubricants

0

मुझे लगता है कि आप या तो एक कस्टम सूची (सूची इंटरफेस को लागू करने) या एक कस्टम इटरेटर बनाना होगा। उदाहरण के लिए:

ArrayList<String> targetList = new ArrayList<String>(); 
ConvertingIterator<String> iterator = new ConvertingIterator<String>(targetList); 
// and here you would have to use a custom List implementation as a source List 
// using the Iterator created above 

लेकिन मुझे संदेह है कि यह दृष्टिकोण आपको बहुत बचाएगा।

12

मेरे answer उस प्रश्न का अपने मामले पर लागू होता है:

import com.google.common.collect.Lists; 
import com.google.common.base.Functions 

List<Integer> integers = Arrays.asList(1, 2, 3, 4); 

List<String> strings = Lists.transform(integers, Functions.toStringFunction()); 

तब्दील सूची मूल संग्रह पर एक दृश्य है, इसलिए परिवर्तन होता है जब गंतव्य List पहुँचा जा सकता है।

1

Lambdaj इसे एक बहुत ही सरल और पठनीय तरीके से करने की अनुमति देता है। उदाहरण के लिए, मान लीजिए कि आपके पास इंटीजर की एक सूची है और आप उन्हें संबंधित स्ट्रिंग प्रस्तुति में रूपांतरित करना चाहते हैं, तो आप ऐसा कुछ लिख सकते हैं;

List<Integer> ints = asList(1, 2, 3, 4); 
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> { 
    public String convert(Integer i) { return Integer.toString(i); } 
}); 

लैम्बडाज केवल परिणाम फ़ंक्शन पर लागू होता है जब आप परिणाम पर पुनरावृत्ति कर रहे होते हैं। एक ही सुविधा का उपयोग करने के लिए एक और संक्षिप्त तरीका भी है। अगला उदाहरण यह मानता है कि आपके पास नाम संपत्ति वाले व्यक्तियों की एक सूची है और आप उस सूची को व्यक्ति के नामों के पुनरावर्तक में परिवर्तित करना चाहते हैं।

Iterator<String> namesIterator = convertIterator(persons, on(Person.class).getName()); 

बहुत आसान। यही है ना

8

के रूप में इटरेटर पैटर्न के लिए एक विकल्प है, तो आप एक अमूर्त सामान्य नक्शाकार वर्ग का उपयोग कर सकते हैं, और केवल ओवरराइड बदलने विधि:

  1. किसी भी डेटा प्रकार के लिए एक सामान्य संग्रह नक्शाकार बनाने
  2. [वैकल्पिक] बनाने तरीकों में से एक पुस्तकालय है कि विभिन्न डेटा प्रकार के बीच बदलने (और विधि ओवरराइड)
  3. उपयोग कि पुस्तकालय

कार्यान्वयन:

// Generic class to transform collections 
public abstract class CollectionTransformer<E, F> { 

    abstract F transform(E e); 

    public List<F> transform(List<E> list) { 
     List<F> newList = new ArrayList<F>(); 
     for (E e : list) { 
      newList.add(transform(e)); 
     } 
     return newList; 
    } 
} 

// Method that transform Integer to String 
// this override the transform method to specify the transformation 
public static List<String> mapIntegerToStringCollection(List<Integer> list) { 

    CollectionTransformer transformer = new CollectionTransformer<Integer, String>() { 
     @Override 
     String transform(Integer e) { 
      return e.toString(); 
     } 
    }; 
    return transformer.transform(list); 
} 

// Example Usage 
List<Integer> integers = Arrays.asList(1,2); 
List<String> strings = mapIntegerToStringCollection(integers); 

यह उपयोगी होगा कि आपको हर बार ट्रांसफॉर्मेशन का उपयोग करना होगा, प्रक्रिया को समाहित करना होगा। तो आप संग्रह मैपर की लाइब्रेरी को बहुत आसान बना सकते हैं।

7

जावा 8 रास्ता:

List<String> original = ...; 
List<Wrapper> converted = original.stream().map(Wrapper::new).collect(Collectors.toList()); 

Wrapper वर्ग मानते हुए एक निर्माता एक String को स्वीकार किया है।

संबंधित मुद्दे