2011-12-26 9 views
22

के साथ जावाबीन की एक सूची फ़िल्टर करना जावा प्रोग्राम में, मेरे पास बीन्स की एक सूची है जिसे मैं किसी विशिष्ट प्रॉपर्टी के आधार पर फ़िल्टर करना चाहता हूं।Google Guava

उदाहरण के लिए, कहें कि मेरे पास व्यक्ति की एक सूची है, जावाबीन, जहां व्यक्ति के नाम 'उनमें से कई गुण हैं।

मेरे पास नामों की एक सूची भी है।

अब मैं उन सभी व्यक्तियों को ढूंढना चाहता हूं जिनके नाम नाम सूची में हैं।

Google Guava का उपयोग करके इस फ़िल्टर को निष्पादित करने का सबसे अच्छा तरीका क्या है?

अब तक, मैंने अपाचे बीनटिल के साथ गुवा को संयोजित करने के बारे में सोचा है, लेकिन यह सुरुचिपूर्ण प्रतीत नहीं होता है।

मुझे यहां एक प्रतिबिंब विस्तार पुस्तकालय भी मिला है: http://code.google.com/p/guava-reflection/, लेकिन मुझे यकीन नहीं है कि इसका उपयोग कैसे करें (वहां थोड़ा दस्तावेज़ है)।

कोई विचार?

पेज। क्या आप बता सकते हैं कि मैं वास्तव में पाइथन सूची समझ को याद करता हूं?

उत्तर

42

इसे अमरूद के बिना पुराने तरीके से करें। (एक अमरूद डेवलपर के रूप में बोलते हुए।)

List<Person> filtered = Lists.newArrayList(); 
for(Person p : allPersons) { 
    if(acceptedNames.contains(p.getName())) { 
     filtered.add(p); 
    } 
} 

आप अमरूद के साथ ऐसा कर सकते हैं, लेकिन जावा अजगर नहीं है, और यह अजगर में बनाने की कोशिश कर सिर्फ अजीब और अपठनीय कोड बनाए रखने के लिए जा रहा है। अमरूद की कार्यात्मक उपयोगिताओं का उपयोग कम से कम किया जाना चाहिए, और केवल तभी जब वे कोड या प्रदर्शन की रेखाओं के लिए एक ठोस और मापनीय लाभ प्रदान करते हैं।

+0

इस समाधान और खान के बीच मुख्य अंतर यह है कि यह समाधान फ़िल्टर किए गए व्यक्तियों वाली एक नई सूची बनाता है, जबकि मेरा मूल सूची पर एक दृश्य बनाता है। चाहे एक या दूसरा प्राथमिकता है, उपयोग-मामले पर निर्भर करता है। –

+0

हां, यह उपयोग के मामले पर निर्भर करता है - लेकिन मैं कहूंगा कि 90% उपयोग मामलों में, पठनीयता सुधार छोटे प्रदर्शन लाभों से अधिक है। –

+3

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

22
Iterable<Person> filtered = Iterables.filter(allPersons, new Predicate<Person>() { 
    @Override 
    public boolean apply(Person p) { 
     return acceptedNames.contains(p.getName()); 
    } 
}); 

तो नाम की अपनी सूची बड़ा है, तो आप बेहतर यह एक सेट में बदलना चाहते हैं (HashSet, अधिमानतः) और कॉल बल्कि सूची की तुलना में इस सेट पर होता है, क्योंकि इसमें शामिल है (1) एक के लिए हे है हैशसेट, और ओ (एन) एक सूची के लिए।

+1

क्या एक सेट के रूप में तब्दील किया जाना चाहिए का उपयोग कर किसी भी सूची फ़िल्टर करने beanutils स्वीकार किए जाते हैं नाम, नहीं व्यक्तियों की सूची की सूची है। यही वह है जिसे कहा जाता है। किसी सेट में व्यक्तियों की सूची को बदलने में कोई अतिरिक्त मूल्य नहीं है। –

+0

@ दूसरे जवाब पर डैनियल की टिप्पणी कुछ संदर्भ प्रदान करती है कि यह कुछ मामलों में क्यों बेहतर होगा। – studgeek

3

मैं लुइस और जेबी उत्तरों के साथ पर्याप्त सहमत नहीं हो सकता। मैं अमरूद प्रतिबिंब पता नहीं था, शायद LambdaJ हो सकता है आप के लिए क्या देख रहे:

// set up 
Person me = new Person("Favio"); 
Person luca = new Person("Luca"); 
Person biagio = new Person("Biagio"); 
Person celestino = new Person("Celestino"); 
Collection<Person> meAndMyFriends = asList(me, luca, biagio, celestino); 

// magic 
Collection<Person> filtered = filter(having(on(Person.class).getName(), 
              isOneOf("Favio", "Luca")), 
            meAndMyFriends); 

// test 
assertThat(filtered, hasItems(me, luca)); 
assertEquals(2, filtered.size()); 

या हो सकता है स्काला, Clojure या ग्रूवी क्या आप के लिए ...

5

देख रहे हैं कर रहे हैं से अपने संदेह की व्याख्या वाक्य:

अब तक, मैं अपाचे beanutils साथ अमरूद के संयोजन के बारे में सोचा है, लेकिन सुरुचिपूर्ण प्रतीत नहीं होता है।

जावा, इतना लोकप्रिय होने के बावजूद, first-class function समर्थन * का अभाव है, subject to change in Java 8, जहाँ आप करने में सक्षम हो जाएगा क्या:

Iterable <Person> filtered = filter(allPersons, (Person p) -> acceptedNames.contains(p.getName())); 

lambdas के साथ और यह सुंदर हो जाएगा।

तब तक आप के बीच चयन किया है:

  • ओल्ड-स्कूल रास्ता (@Louis की तरह लिखा था)
  • वर्बोज़ अमरूद फिल्टर (@ जेबी का जवाब)
  • या अन्य कार्यात्मक जावा लाइब्रेरीज (@ superfav के जवाब)।

मैं भी कि Guava-way would be to create immutable collection @ करने के लिए लोइस के जवाब जोड़ने के लिए चाहते हैं, क्योंकि they are better than unmodifiable है, जो भी यहोशू बलोच द्वारा **प्रभावी जावा में मद 15, कम से कम अस्थिरता में वर्णित है:

ImmutableList.Builder<Person> builder = ImmutableList.builder(); 
for (final Person p : allPersons) { 
    if (acceptedNames.contains(p.getName())) { 
     builder.add(p); 
    } 
} 
ImmutableList<Person> filtered = builder.build(); 

(यह कार्यान्वयन विस्तार है कि ImmutableList.Builder हुड के तहत अस्थायी ArrayList बनाता है)।

*: यह मुझे बहुत परेशान करती है, मैं अजगर, जावास्क्रिप्ट और पर्ल दुनिया से आया है, where functions are treated better

**: अमरूद और बलोच हैं कसकर कई मायनों में मिलकर;)

2

अमरूद-प्रतिबिंब के डेवलपर के रूप में बोलते हुए, मुझे खेद है कि मैंने इस परियोजना को इस तरह के शुरुआती चरण में छोड़ दिया है (मेरे पास एक दिन का काम है और एक पत्नी & बच्चे हैं :-))।

Iterable<Object> thingsWithNames = 
    Iterables.filter(someData, 
        // this is a Predicate, obviously 
        BeanProperties.hasBeanProperty("name", String.class)); 

मौजूदा कोड वहाँ के बारे में 60% है, इसलिए यदि आप रुचि रखते हैं, कृपया मुझसे संपर्क और शायद हम इस एक साथ समाप्त हो गया प्राप्त कर सकते हैं: मेरी दृष्टि कुछ की तरह था।

0

आप एकल पिरोया आवेदन में प्रयोग कर एक LinkedList (या किसी अन्य संग्रह जो oprations को दूर बहुत श्रमसाध्य नहीं है) तो सबसे प्रभावशाली उपाय है:

final Iterator<User> userIterator = users.iterator(); 
while (userIterator.hasNext()) { 
    if (/* your condition for exclusion */) { 
     userIterator.remove(); 
    } 
} 
+0

ओच! यह काम नहीं करेगा क्योंकि आप सूची –

+0

पर समवर्ती पहुंच में भाग लेंगे धन्यवाद! मैंने अपना जवाब तय कर दिया है। –

0
Java8 शैली आप धारा का उपयोग कर सकते के साथ

+ अपने लक्ष्य को प्राप्त करने के लिए फ़िल्टर करें।

persons.stream() 
      .filter(p -> names.contains(p.getName())) 
      .collect(Collectors.toList()); 
0

Java8 के साथ आप उपयोग कर सकते हैं Collection.removeIf()

List<Person> theList = ...; 
theList.removeIf(
    (Person p)->"paul".equals(p.getName()) 
); 

वर्तमान सूची को संशोधित पाठ्यक्रम की यह इच्छा।

0

यहाँ अमरूद का उपयोग कर जेनरिक का उपयोग करने का एक उदाहरण है, अनुरोध किया मैच

/** 
* Filter List 
* 
* @param inputList 
* @param requestMatch 
* @param invokeMethod 
* @return 
*/ 
public static <T> Iterable<T> predicateFilterList(List<T> inputList, final String requestMatch, 
     final String invokeMethod) { 
    Predicate<T> filtered = new Predicate<T>() { 
     @Override 
     public boolean apply(T input) { 
      boolean ok = false; 
      try { 
       ok = BeanUtils.getProperty(input, invokeMethod).equalsIgnoreCase(requestMatch); 
      } 
      catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return ok; 
     } 
    }; 
    return Iterables.filter(inputList, filtered); 
} 
संबंधित मुद्दे