दिलचस्प पोस्ट
डेटाबेस सामान्य रूप क्या हैं, आप उन्हें आसानी से कैसे लागू कर सकते हैं और आप उदाहरण दे सकते हैं? गूगल मैप्स एपीआई v3.19 इंटरनेट एक्सप्लोरर क्वेरक्स मोड में टूटी हुई है दूरदराज के रिपॉजिटरी पर नहीं रह जाने वाले स्थानीय टैग निकालें मैं PHP में उपवर्तन संशोधन संख्या कैसे प्राप्त करूं? क्लोज एंड डिस्पोज़ – कॉल करने के लिए? एएसपी.नेट एमवीसी: डेटाएनेटेशन द्वारा कस्टम वैल्यूशन साबुन क्लाइंट उदाहरण कार्य करना कई पंक्तियों पर मूल्य विभाजित करें बच्चे के थ्रेड्स पूरा होने तक प्रतीक्षा करें: जावा एंड्रॉइड: गैलरी से छवि का चयन करें, फिर फसल करें और छवि दृश्य में दिखाएं स्ट्रैक्ट्स के 2 डी सरणी को पास करना कैसे एक छवि (एनीमेशन) को स्थानांतरित करने के लिए? Javafx टेबलव्यूले सभी कॉलम में डेटा नहीं दिखा रहा है जावा लिंक्डएचशैप पहले या अंतिम प्रविष्टि प्राप्त करें एक माउस के एक्स / वाई निर्देशांक प्राप्त करना एक छवि पर क्लिक करता है

ऑब्जेक्ट वैल्यू से ग्रुपिंग, गिनती और फिर अधिकतम ऑब्जेक्ट एट्रिब्यूट द्वारा समूह कुंजी सेट करना

मैंने जावा 8 स्ट्रीम एपीआई का उपयोग करते हुए एक समाधान लिखने में कामयाब हो गया है जो पहले ऑब्जेक्ट रूट की एक सूची को इसके मूल्य से समूह में जोड़ता है और फिर प्रत्येक समूह में वस्तुओं की संख्या की गणना करता है। मैपिंग रूट -> लांग यहां कोड है:

Map<Route, Long> routesCounted = routes.stream() .collect(Collectors.groupingBy(gr -> gr, Collectors.counting())); 

और रूट क्लास:

 public class Route implements Comparable<Route> { private long lastUpdated; private Cell startCell; private Cell endCell; private int dropOffSize; public Route(Cell startCell, Cell endCell, long lastUpdated) { this.startCell = startCell; this.endCell = endCell; this.lastUpdated = lastUpdated; } public long getLastUpdated() { return this.lastUpdated; } public void setLastUpdated(long lastUpdated) { this.lastUpdated = lastUpdated; } public Cell getStartCell() { return startCell; } public void setStartCell(Cell startCell) { this.startCell = startCell; } public Cell getEndCell() { return endCell; } public void setEndCell(Cell endCell) { this.endCell = endCell; } public int getDropOffSize() { return this.dropOffSize; } public void setDropOffSize(int dropOffSize) { this.dropOffSize = dropOffSize; } @Override /** * Compute hash code by using Apache Commons Lang HashCodeBuilder. */ public int hashCode() { return new HashCodeBuilder(43, 59) .append(this.startCell) .append(this.endCell) .toHashCode(); } @Override /** * Compute equals by using Apache Commons Lang EqualsBuilder. */ public boolean equals(Object obj) { if (!(obj instanceof Route)) return false; if (obj == this) return true; Route route = (Route) obj; return new EqualsBuilder() .append(this.startCell, route.startCell) .append(this.endCell, route.endCell) .isEquals(); } @Override public int compareTo(Route route) { if (this.dropOffSize < route.dropOffSize) return -1; else if (this.dropOffSize > route.dropOffSize) return 1; else { // if contains drop off timestamps, order by last timestamp in drop off // the highest timestamp has preceding if (this.lastUpdated < route.lastUpdated) return -1; else if (this.lastUpdated > route.lastUpdated) return 1; else return 0; } } } 

मैं अतिरिक्त रूप से क्या हासिल करना चाहूंगा, यह है कि हर समूह के लिए सबसे महत्वपूर्ण अंतिम अद्यतन मूल्य वाला एक होगा। मैं पहले से ही इस समाधान को देख रहा था लेकिन मुझे नहीं पता कि मूल्य और रूट अधिकतम अंतिम अद्यतन मूल्य से गिनती और समूह को गठबंधन कैसे करें। मैं क्या हासिल करना चाहता हूं, इसका उदाहरण यहां दिया गया है:

उदाहरण:

 List<Route> routes = new ArrayList<>(); routes.add(new Route(new Cell(1, 2), new Cell(2, 1), 1200L)); routes.add(new Route(new Cell(3, 2), new Cell(2, 5), 1800L)); routes.add(new Route(new Cell(1, 2), new Cell(2, 1), 1700L)); 

इसके लिए परिवर्तित किया जाना चाहिए:

 Map<Route, Long> routesCounted = new HashMap<>(); routesCounted.put(new Route(new Cell(1, 2), new Cell(2, 1), 1700L), 2); routesCounted.put(new Route(new Cell(3, 2), new Cell(2, 5), 1800L), 1); 

ध्यान दें कि मैपिंग की कुंजी, जिसकी गणना 2 राउट्स सबसे बड़ा अंतिम अद्यतन मूल्य वाला एक है

Solutions Collecting From Web of "ऑब्जेक्ट वैल्यू से ग्रुपिंग, गिनती और फिर अधिकतम ऑब्जेक्ट एट्रिब्यूट द्वारा समूह कुंजी सेट करना"

यहाँ एक दृष्टिकोण है सूची में पहला समूह और फिर सूचियों को उन मूल्यों में संसाधित करें जिन्हें आप वास्तव में चाहते हैं:

 import static java.util.Comparator.comparingLong; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toMap; Map<Route,Integer> routeCounts = routes.stream() .collect(groupingBy(x -> x)) .values().stream() .collect(toMap( lst -> lst.stream().max(comparingLong(Route::getLastUpdated)).get(), List::size )); 

आप एक सार "पुस्तकालय" विधि को परिभाषित कर सकते हैं जो दो कलेक्टरों को एक में जोड़ती है:

 static <T, A1, A2, R1, R2, R> Collector<T, ?, R> pairing(Collector<T, A1, R1> c1, Collector<T, A2, R2> c2, BiFunction<R1, R2, R> finisher) { EnumSet<Characteristics> c = EnumSet.noneOf(Characteristics.class); c.addAll(c1.characteristics()); c.retainAll(c2.characteristics()); c.remove(Characteristics.IDENTITY_FINISH); return Collector.of(() -> new Object[] {c1.supplier().get(), c2.supplier().get()}, (acc, v) -> { c1.accumulator().accept((A1)acc[0], v); c2.accumulator().accept((A2)acc[1], v); }, (acc1, acc2) -> { acc1[0] = c1.combiner().apply((A1)acc1[0], (A1)acc2[0]); acc1[1] = c2.combiner().apply((A2)acc1[1], (A2)acc2[1]); return acc1; }, acc -> { R1 r1 = c1.finisher().apply((A1)acc[0]); R2 r2 = c2.finisher().apply((A2)acc[1]); return finisher.apply(r1, r2); }, c.toArray(new Characteristics[c.size()])); } 

इसके बाद वास्तविक ऑपरेशन इस तरह दिख सकता है:

 Map<Route, Long> result = routes.stream() .collect(Collectors.groupingBy(Function.identity(), pairing(Collectors.maxBy(Comparator.comparingLong(Route::getLastUpdated)), Collectors.counting(), (route, count) -> new AbstractMap.SimpleEntry<>(route.get(), count)) )) .values().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); 

अद्यतन: इस तरह के कलेक्टर मेरे स्ट्रीमएक्स लाइब्रेरी में उपलब्ध हैं: MoreCollectors.pairing() । इसके अलावा इसी कलेक्टर को जूल पुस्तकालय में लागू किया गया है, ताकि आप pairing बजाय Tuple.collectors उपयोग कर सकें।

बदलता हुआ बराबर और हैशोड केवल प्रारंभिक सेल और अंत सेल पर निर्भर होने के लिए।

 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Cell cell = (Cell) o; if (a != cell.a) return false; if (b != cell.b) return false; return true; } @Override public int hashCode() { int result = a; result = 31 * result + b; return result; } 

मेरा समाधान इस तरह दिखता है:

 Map<Route, Long> routesCounted = routes.stream() .sorted((r1,r2)-> (int)(r2.lastUpdated - r1.lastUpdated)) .collect(Collectors.groupingBy(gr -> gr, Collectors.counting())); 

बेशक int को कास्ट करने के लिए कुछ अधिक विनियोजित कुछ के साथ प्रतिस्थापित किया जाना चाहिए।

सिद्धांत रूप में ऐसा लगता है कि यह एक पारित होने में योग्य होना चाहिए। सामान्य शिकन यह है कि इसके लिए एक तदर्थ टपल या जोड़ी की आवश्यकता होती है, इस मामले में एक Route और गिनती के साथ। चूंकि जावा में इनकी कमी है, इसलिए हम लंबाई 2 के एक ऑब्जेक्ट सरणी का उपयोग करते हैं (जैसा कि टैगिर वालेव के उत्तर में दिखाया गया है), या ऐबस्ट्रैक्टमैप। सिंपल इम्प्रूटेबल एंटररी , या एक काल्पनिक Pair<A,B> वर्ग।

विकल्प एक कम मूल्य वर्ग लिखना है जो एक Route और एक गिनती रखता है। बेशक ऐसा करने में कुछ दर्द हो रहा है, लेकिन इस मामले में मुझे लगता है कि यह भुगतान करता है क्योंकि यह संयोजन तर्क को प्रस्तुत करने का स्थान प्रदान करता है। इसके बदले में धारा संचालन को सरल करता है।

यहां मान वर्ग में एक Route और एक गिन है:

 class RouteCount { final Route route; final long count; private RouteCount(Route r, long c) { this.route = r; count = c; } public static RouteCount fromRoute(Route r) { return new RouteCount(r, 1L); } public static RouteCount combine(RouteCount rc1, RouteCount rc2) { Route recent; if (rc1.route.getLastUpdated() > rc2.route.getLastUpdated()) { recent = rc1.route; } else { recent = rc2.route; } return new RouteCount(recent, rc1.count + rc2.count); } } 

सुंदर सीधा, लेकिन combine विधि नोटिस। यह Route चयन करके दो RouteCount मानों को जोड़ता है जो कि हाल ही में अद्यतन किया गया है और गणनाओं के योग का उपयोग कर रहा है। अब जब हमारे पास यह मान वर्ग है, तो हम चाहते हैं कि परिणाम प्राप्त करने के लिए हम एक एक-पास स्ट्रीम लिख सकते हैं:

  Map<Route, RouteCount> counted = routes.stream() .collect(groupingBy(route -> route, collectingAndThen( mapping(RouteCount::fromRoute, reducing(RouteCount::combine)), Optional::get))); 

अन्य उत्तरों की तरह, यह समूह शुरूआती और समाप्ति सेल पर आधारित तुल्यता कक्षाओं में रूट करता है। कुंजी के रूप में इस्तेमाल किया गया वास्तविक Route उदाहरण महत्वपूर्ण नहीं है; यह सिर्फ इसकी कक्षा का प्रतिनिधि है मूल्य एक एकल RouteCount होगा जिसमें Route उदाहरण मौजूद हैं जो हाल ही में अपडेट किए गए हैं, साथ ही समान Route आवृत्तियों की गणना के साथ।

जिस तरह से यह काम करता है वह है कि प्रत्येक Route आवृत्ति जिसका एक ही प्रारंभ और अंत कोशिकाओं है, फिर groupingBy के डाउनस्ट्रीम कलेक्टर में खिलाया जाता है। यह mapping कलेक्टर Route RouteCount इंस्टेंस में मैप्स करता है, फिर इसे reducing कलेक्टर के पास जाता है जो ऊपर वर्णित संयोजन तर्क का उपयोग करते हुए उदाहरणों को कम करता है। collectingAndThen का और फिर भाग और फिर Optional<RouteCount> से उस मूल्य को अर्क कर देता है जो reducing कलेक्टर पैदा करता है।

(आम तौर पर एक नंगे get खतरनाक है, लेकिन हम इस कलेक्टर को तब तक नहीं प्राप्त करते जब तक कि कम से कम एक मूल्य उपलब्ध न हो। इसलिए इस मामले में सुरक्षित रहें।)