99import java .lang .reflect .Array ;
1010import java .util .ArrayList ;
1111import java .util .Collection ;
12- import java .util .Collections ;
1312import java .util .Iterator ;
1413import java .util .LinkedHashMap ;
1514import java .util .List ;
1918import java .util .OptionalInt ;
2019import java .util .Set ;
2120import java .util .concurrent .CompletableFuture ;
21+ import java .util .function .BiFunction ;
2222import java .util .function .BinaryOperator ;
2323import java .util .function .Function ;
2424import java .util .function .Predicate ;
2525import java .util .function .Supplier ;
26+ import java .util .stream .Collectors ;
2627import java .util .stream .Stream ;
2728
2829import static java .util .Collections .singletonList ;
30+ import static java .util .function .Function .identity ;
31+ import static java .util .stream .Collectors .mapping ;
2932
3033@ Internal
3134public class FpKit {
3235
3336 //
3437 // From a list of named things, get a map of them by name, merging them according to the merge function
3538 public static <T > Map <String , T > getByName (List <T > namedObjects , Function <T , String > nameFn , BinaryOperator <T > mergeFunc ) {
36- return toMap (namedObjects , nameFn , mergeFunc );
37- }
38-
39- //
40- // From a collection of keyed things, get a map of them by key, merging them according to the merge function
41- public static <T , NewKey > Map <NewKey , T > toMap (Collection <T > collection , Function <T , NewKey > keyFunction , BinaryOperator <T > mergeFunc ) {
42- Map <NewKey , T > resultMap = new LinkedHashMap <>();
43- for (T obj : collection ) {
44- NewKey key = keyFunction .apply (obj );
45- if (resultMap .containsKey (key )) {
46- T existingValue = resultMap .get (key );
47- T mergedValue = mergeFunc .apply (existingValue , obj );
48- resultMap .put (key , mergedValue );
49- } else {
50- resultMap .put (key , obj );
51- }
52- }
53- return resultMap ;
39+ return namedObjects .stream ().collect (Collectors .toMap (
40+ nameFn ,
41+ identity (),
42+ mergeFunc ,
43+ LinkedHashMap ::new )
44+ );
5445 }
5546
5647 // normal groupingBy but with LinkedHashMap
5748 public static <T , NewKey > Map <NewKey , ImmutableList <T >> groupingBy (Collection <T > list , Function <T , NewKey > function ) {
58- return filterAndGroupingBy ( list , t -> true , function );
49+ return list . stream (). collect ( Collectors . groupingBy ( function , LinkedHashMap :: new , mapping ( Function . identity (), ImmutableList . toImmutableList ())) );
5950 }
6051
61- @ SuppressWarnings ("unchecked" )
6252 public static <T , NewKey > Map <NewKey , ImmutableList <T >> filterAndGroupingBy (Collection <T > list ,
6353 Predicate <? super T > predicate ,
6454 Function <T , NewKey > function ) {
65- //
66- // The cleanest version of this code would have two maps, one of immutable list builders and one
67- // of the built immutable lists. BUt we are trying to be performant and memory efficient so
68- // we treat it as a map of objects and cast like its Java 4x
69- //
70- Map <NewKey , Object > resutMap = new LinkedHashMap <>();
71- for (T item : list ) {
72- if (predicate .test (item )) {
73- NewKey key = function .apply (item );
74- // we have to use an immutable list builder as we built it out
75- ((ImmutableList .Builder <Object >) resutMap .computeIfAbsent (key , k -> ImmutableList .builder ()))
76- .add (item );
77- }
78- }
79- if (resutMap .isEmpty ()) {
80- return Collections .emptyMap ();
81- }
82- // Convert builders to ImmutableLists in place to avoid an extra allocation
83- // yes the code is yuck - but its more performant yuck!
84- resutMap .replaceAll ((key , builder ) ->
85- ((ImmutableList .Builder <Object >) builder ).build ());
86-
87- // make it the right shape - like as if generics were never invented
88- return (Map <NewKey , ImmutableList <T >>) (Map <?, ?>) resutMap ;
55+ return list .stream ().filter (predicate ).collect (Collectors .groupingBy (function , LinkedHashMap ::new , mapping (Function .identity (), ImmutableList .toImmutableList ())));
8956 }
9057
91- public static <T , NewKey > Map <NewKey , T > toMapByUniqueKey ( Collection <T > list , Function <T , NewKey > keyFunction ) {
92- return toMap ( list , keyFunction , throwingMerger ( ));
58+ public static <T , NewKey > Map <NewKey , ImmutableList < T >> groupingBy ( Stream <T > stream , Function <T , NewKey > function ) {
59+ return stream . collect ( Collectors . groupingBy ( function , LinkedHashMap :: new , mapping ( Function . identity (), ImmutableList . toImmutableList ()) ));
9360 }
9461
62+ public static <T , NewKey > Map <NewKey , T > groupingByUniqueKey (Collection <T > list , Function <T , NewKey > keyFunction ) {
63+ return list .stream ().collect (Collectors .toMap (
64+ keyFunction ,
65+ identity (),
66+ throwingMerger (),
67+ LinkedHashMap ::new )
68+ );
69+ }
9570
96- private static final BinaryOperator <Object > THROWING_MERGER_SINGLETON = (u , v ) -> {
97- throw new IllegalStateException (String .format ("Duplicate key %s" , u ));
98- };
71+ public static <T , NewKey > Map <NewKey , T > groupingByUniqueKey (Stream <T > stream , Function <T , NewKey > keyFunction ) {
72+ return stream .collect (Collectors .toMap (
73+ keyFunction ,
74+ identity (),
75+ throwingMerger (),
76+ LinkedHashMap ::new )
77+ );
78+ }
9979
10080 private static <T > BinaryOperator <T > throwingMerger () {
101- //noinspection unchecked
102- return (BinaryOperator <T >) THROWING_MERGER_SINGLETON ;
81+ return (u , v ) -> {
82+ throw new IllegalStateException (String .format ("Duplicate key %s" , u ));
83+ };
10384 }
10485
10586
@@ -259,6 +240,11 @@ public static <T> List<T> valuesToList(Map<?, T> map) {
259240 return new ArrayList <>(map .values ());
260241 }
261242
243+ public static <K , V , U > List <U > mapEntries (Map <K , V > map , BiFunction <K , V , U > function ) {
244+ return map .entrySet ().stream ().map (entry -> function .apply (entry .getKey (), entry .getValue ())).collect (Collectors .toList ());
245+ }
246+
247+
262248 public static <T > List <List <T >> transposeMatrix (List <? extends List <T >> matrix ) {
263249 int rowCount = matrix .size ();
264250 int colCount = matrix .get (0 ).size ();
@@ -286,12 +272,10 @@ public static <T> List<T> flatList(Collection<List<T>> listLists) {
286272 }
287273
288274 public static <T > Optional <T > findOne (Collection <T > list , Predicate <T > filter ) {
289- for (T t : list ) {
290- if (filter .test (t )) {
291- return Optional .of (t );
292- }
293- }
294- return Optional .empty ();
275+ return list
276+ .stream ()
277+ .filter (filter )
278+ .findFirst ();
295279 }
296280
297281 public static <T > T findOneOrNull (List <T > list , Predicate <T > filter ) {
@@ -308,13 +292,10 @@ public static <T> int findIndex(List<T> list, Predicate<T> filter) {
308292 }
309293
310294 public static <T > List <T > filterList (Collection <T > list , Predicate <T > filter ) {
311- List <T > result = new ArrayList <>();
312- for (T t : list ) {
313- if (filter .test (t )) {
314- result .add (t );
315- }
316- }
317- return result ;
295+ return list
296+ .stream ()
297+ .filter (filter )
298+ .collect (Collectors .toList ());
318299 }
319300
320301 public static <T > Set <T > filterSet (Collection <T > input , Predicate <T > filter ) {
@@ -371,10 +352,9 @@ public static <T> Supplier<T> interThreadMemoize(Supplier<T> delegate) {
371352 /**
372353 * Faster set intersection.
373354 *
374- * @param <T> for two
355+ * @param <T> for two
375356 * @param set1 first set
376357 * @param set2 second set
377- *
378358 * @return intersection set
379359 */
380360 public static <T > Set <T > intersection (Set <T > set1 , Set <T > set2 ) {
0 commit comments