2012-05-11 9 views
26

द्वारा संग्रह को विभाजित करने के लिए लाइब्रेरी विधि मेरे पास ऑब्जेक्ट्स का एक संग्रह है जिसे मैं दो संग्रहों में विभाजित करना चाहता हूं, जिनमें से एक भविष्यवाणी करता है और इनमें से एक भविष्यवाणी में विफल रहता है। मैं उम्मीद कर रहा था कि ऐसा करने के लिए Guava विधि होगी, लेकिन निकटतम वे filter है, जो मुझे अन्य संग्रह नहीं देता है।एक अनुमानित

मैं छवि विधि के हस्ताक्षर कुछ इस तरह होगा होगा:

public static <E> Pair<Collection<E>, Collection<E>> partition(Collection<E> source, Predicate<? super E> predicate) 

मुझे पता है यह अपने आप कोड करने के लिए सबसे तेज़ है, लेकिन मैं करता हूँ कि मैं क्या चाहते हैं एक मौजूदा पुस्तकालय विधि के लिए देख रहा हूँ ।

+0

ध्यान दें कि के मामले में अग्रिम partiotion कुंजी में जाना जाता है के सीमित सेट यह बहुत अधिक कुशल जीसी बुद्धिमान हो सकता है सिर्फ संग्रह एक बार प्रत्येक यात्रा पर सभी अलग-कुंजी आइटम लंघन प्रत्येक विभाजन कुंजी के लिए और अधिक पुनरावृत्ति करने के लिए। – Vadzim

+0

एक और जीसी-अनुकूल और encapsulated दृष्टिकोण दोनों मूल संग्रह के आसपास जावा 8 फ़िल्टरिंग रैपर धाराओं का उपयोग कर रहा है: https://stackoverflow.com/questions/19940319/can-you-split-a-stream-into-two-streams – Vadzim

उत्तर

24

अमरूद का Multimaps.index का उपयोग करें।

यहां एक उदाहरण है, जो दो भागों में शब्दों की एक सूची को विभाजित करता है: जिनके पास लंबाई> 3 है और जो नहीं हैं।

List<String> words = Arrays.asList("foo", "bar", "hello", "world"); 

ImmutableListMultimap<Boolean, String> partitionedMap = Multimaps.index(words, new Function<String, Boolean>(){ 
    @Override 
    public Boolean apply(String input) { 
     return input.length() > 3; 
    } 
}); 
System.out.println(partitionedMap); 

प्रिंट:

false=[foo, bar], true=[hello, world] 
+1

धन्यवाद, मैं वहां देखने के लिए सोचा नहीं होता। –

+4

आप पहले से ही एक विधेय है, तो आप इसे Functions.forPredicate के साथ एक समारोह में बदल सकते हैं। – roryparle

+4

जावा 8 के लिए अद्यतन: स्ट्रीमिंग पैकेज में एक समान विधि भी प्रदान की जाती है 'java.util.stream.Collectors # groupingBy (java.util.function.Function <....>) ' यह' words.stream() संग्रह की तरह जाता है। (संग्राहक.groupingBy (func)) ' –

3

आप Eclipse Collections (पूर्व में जी एस संग्रह) का उपयोग कर रहे हैं, तो आप सब RichIterables पर partition विधि का उपयोग कर सकते हैं।

MutableList<Integer> integers = FastList.newListWith(-3, -2, -1, 0, 1, 2, 3); 
PartitionMutableList<Integer> result = integers.partition(IntegerPredicates.isEven()); 
Assert.assertEquals(FastList.newListWith(-2, 0, 2), result.getSelected()); 
Assert.assertEquals(FastList.newListWith(-3, -1, 1, 3), result.getRejected()); 

एक कस्टम प्रकार, PartitionMutableList उपयोग करने का कारण, बजाय Pair getSelected() और getRejected के लिए covariant वापसी प्रकार अनुमति देने के लिए है()। उदाहरण के लिए, MutableCollection विभाजन करना सूचियों के बजाय दो संग्रह देता है।

MutableCollection<Integer> integers = ...; 
PartitionMutableCollection<Integer> result = integers.partition(IntegerPredicates.isEven()); 
MutableCollection<Integer> selected = result.getSelected(); 

तो अपने संग्रह के लिए एक RichIterable नहीं है, तो आप अभी भी ग्रहण संग्रह में स्थिर उपयोगिता का उपयोग कर सकते हैं।

PartitionIterable<Integer> partitionIterable = Iterate.partition(integers, IntegerPredicates.isEven()); 
PartitionMutableList<Integer> partitionList = ListIterate.partition(integers, IntegerPredicates.isEven()); 

नोट: मैं ग्रहण संग्रह के लिए एक committer हूँ।

8
नई जावा 8 विशेषताएं ( stream और lambda epressions) के साथ

, आप लिख सकते हैं:

List<String> words = Arrays.asList("foo", "bar", "hello", "world"); 

Map<Boolean, List<String>> partitionedMap = 
     words.stream().collect(
       Collectors.partitioningBy(word -> word.length() > 3)); 

System.out.println(partitionedMap); 
0

Apache Commons CollectionsIterableUtilsIterable वस्तुओं एक या अधिक विधेय के आधार पर विभाजन के लिए तरीके प्रदान करता है। (partition(...) विधियों की तलाश करें।)

0

ध्यान दें कि अग्रिम पार्टिशन कुंजी में ज्ञात सीमित सेट के मामले में यह प्रत्येक विभाजन कुंजी के लिए एक बार फिर संग्रह को पुन: सक्रिय करने के लिए और अधिक कुशल हो सकता है, प्रत्येक पर सभी अलग-अलग कुंजी आइटम छोड़ना यात्रा। चूंकि यह कचरा कलेक्टर के लिए कई नई वस्तुओं को आवंटित नहीं करेगा।

LocalDate start = LocalDate.now().with(TemporalAdjusters.firstDayOfYear()); 
LocalDate endExclusive = LocalDate.now().plusYears(1); 
List<LocalDate> daysCollection = Stream.iterate(start, date -> date.plusDays(1)) 
     .limit(ChronoUnit.DAYS.between(start, endExclusive)) 
     .collect(Collectors.toList()); 
List<DayOfWeek> keys = Arrays.asList(DayOfWeek.values()); 

for (DayOfWeek key : keys) { 
    int count = 0; 
    for (LocalDate day : daysCollection) { 
     if (key == day.getDayOfWeek()) { 
      ++count; 
     } 
    } 
    System.out.println(String.format("%s: %d days in this year", key, count)); 
} 

एक और दोनों जीसी के अनुकूल है और समझाया दृष्टिकोण मूल संग्रह के आसपास जावा 8 छानने आवरण धाराओं उपयोग कर रहा है:

List<AbstractMap.SimpleEntry<DayOfWeek, Stream<LocalDate>>> partitions = keys.stream().map(
     key -> new AbstractMap.SimpleEntry<>(
       key, daysCollection.stream().filter(
        day -> key == day.getDayOfWeek()))) 
     .collect(Collectors.toList()); 
// partitions could be passed somewhere before being used 
partitions.forEach(pair -> System.out.println(
     String.format("%s: %d days in this year", pair.getKey(), pair.getValue().count()))); 

दोनों के टुकड़े प्रिंट इस:

MONDAY: 57 days in this year 
TUESDAY: 57 days in this year 
WEDNESDAY: 57 days in this year 
THURSDAY: 57 days in this year 
FRIDAY: 56 days in this year 
SATURDAY: 56 days in this year 
SUNDAY: 56 days in this year 
संबंधित मुद्दे