diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/ImmutableCollection.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/ImmutableCollection.java index 2b5fc23b..8729323b 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/ImmutableCollection.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/ImmutableCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,11 @@ default ImmutableCollection peek(Consumer consumer) default ImmutableBag countBy(Function function) { var counts = MutableBag.empty(); - this.forEach(each -> counts.add(function.apply(each))); - return counts.toImmutable(); + return this.map(function, counts).toImmutable(); + } + + default ImmutableBag countByEach(Function> function) + { + return this.flatMap(function, MutableBag.empty()).toImmutable(); } } diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableBag.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableBag.java index b55ec988..cd94b694 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableBag.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableBag.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,44 +79,27 @@ default MutableBag peek(Consumer consumer) default MutableBag filter(Predicate predicate) { var mutableBag = MutableBag.empty(); - for (T each : this) - { - if (predicate.test(each)) - { - mutableBag.add(each); - } - } - return mutableBag; + return this.filter(predicate, mutableBag); } @Override default MutableBag filterNot(Predicate predicate) { - var mutableBag = MutableBag.empty(); - for (T each : this) - { - if (!predicate.test(each)) - { - mutableBag.add(each); - } - } - return mutableBag; + return this.filter(predicate.negate()); } @Override default MutableBag map(Function function) { var mutableBag = MutableBag.empty(); - this.forEach(each -> mutableBag.add(function.apply(each))); - return mutableBag; + return this.map(function, mutableBag); } @Override default MutableBag flatMap(Function> function) { var mutableBag = MutableBag.empty(); - this.forEach(each -> mutableBag.addAllIterable(function.apply(each))); - return mutableBag; + return this.flatMap(function, mutableBag); } default ArrayListMultimap groupBy(Function function) diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableCollection.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableCollection.java index d0f1c892..46b07977 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableCollection.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,15 +29,12 @@ default boolean addAllIterable(Iterable iterable) { return this.addAll(collection); } - else + boolean result = false; + for (T each : iterable) { - boolean result = false; - for (T each : iterable) - { - result |= this.add(each); - } - return result; + result |= this.add(each); } + return result; } @Override @@ -71,4 +68,9 @@ default MutableBag countBy(Function function) this.forEach(each -> counts.add(function.apply(each))); return counts; } + + default MutableBag countByEach(Function> function) + { + return this.flatMap(function, MutableBag.empty()); + } } diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableList.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableList.java index 09a5fb33..6c2d02ba 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableList.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableList.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,44 +81,27 @@ default MutableList asUnmodifiable() default MutableList filter(Predicate predicate) { var mutableList = MutableList.empty(); - for (T each : this) - { - if (predicate.test(each)) - { - mutableList.add(each); - } - } - return mutableList; + return this.filter(predicate, mutableList); } @Override default MutableList filterNot(Predicate predicate) { - var mutableList = MutableList.empty(); - for (T each : this) - { - if (!predicate.test(each)) - { - mutableList.add(each); - } - } - return mutableList; + return this.filter(predicate.negate()); } @Override default MutableList map(Function function) { var mutableList = MutableList.empty(); - this.forEach(each -> mutableList.add(function.apply(each))); - return mutableList; + return this.map(function, mutableList); } @Override default MutableList flatMap(Function> function) { var mutableList = MutableList.empty(); - this.forEach(each -> mutableList.addAllIterable(function.apply(each))); - return mutableList; + return this.flatMap(function, mutableList); } @Override @@ -135,6 +118,13 @@ default MutableListMultimap groupBy(Function f return multimap; } + default MutableListMultimap groupByEach(Function> function) + { + var multimap = MutableListMultimap.empty(); + this.forEach(each -> function.apply(each).forEach(key -> multimap.put(key, each))); + return multimap; + } + default MutableListMultimap groupByUnmodifiable(Function function) { var multimap = this.groupBy(function); diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableSet.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableSet.java index 6bacd4cb..60b55cde 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableSet.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/MutableSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,44 +78,27 @@ default java.util.Set asUnmodifiable() default MutableSet filter(Predicate predicate) { var mutableSet = MutableSet.empty(); - for (T each : this) - { - if (predicate.test(each)) - { - mutableSet.add(each); - } - } - return mutableSet; + return this.filter(predicate, mutableSet); } @Override default MutableSet filterNot(Predicate predicate) { - var mutableSet = MutableSet.empty(); - for (T each : this) - { - if (!predicate.test(each)) - { - mutableSet.add(each); - } - } - return mutableSet; + return this.filter(predicate.negate()); } @Override default MutableSet map(Function function) { var mutableSet = MutableSet.empty(); - this.forEach(each -> mutableSet.add(function.apply(each))); - return mutableSet; + return this.map(function, mutableSet); } @Override default MutableSet flatMap(Function> function) { var mutableSet = MutableSet.empty(); - this.forEach(each -> mutableSet.addAllIterable(function.apply(each))); - return mutableSet; + return this.flatMap(function, mutableSet); } default MutableSetMultimap groupBy(Function function) diff --git a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/RichIterable.java b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/RichIterable.java index 5c617e9d..09758ce3 100644 --- a/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/RichIterable.java +++ b/deck-of-cards-kata/src/main/java/bnymellon/codekatas/deckofcards/custom/collections/RichIterable.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Bank of New York Mellon. + * Copyright 2023 The Bank of New York Mellon. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,11 @@ public interface RichIterable extends Iterable boolean isEmpty(); + default boolean notEmpty() + { + return !this.isEmpty(); + } + default Stream stream() { throw new UnsupportedOperationException(); @@ -39,12 +44,41 @@ default Stream stream() RichIterable filter(Predicate predicate); + default > R filter(Predicate predicate, R target) + { + this.forEach(each -> + { + if (predicate.test(each)) + { + target.add(each); + } + }); + return target; + } + RichIterable filterNot(Predicate predicate); + default > R filterNot(Predicate predicate, R target) + { + return this.filter(predicate.negate(), target); + } + RichIterable map(Function function); + default > R map(Function function, R target) + { + this.forEach(each -> target.add(function.apply(each))); + return target; + } + RichIterable flatMap(Function> function); + default > R flatMap(Function> function, R target) + { + this.forEach(each -> target.addAllIterable(function.apply(each))); + return target; + } + default RichIterable peek(Consumer consumer) { this.forEach(consumer); @@ -80,6 +114,11 @@ default boolean anyMatch(Predicate predicate) return false; } + default boolean containsBy(Function function, V value) + { + return this.anyMatch(each -> value.equals(function.apply(each))); + } + default boolean allMatch(Predicate predicate) { for (T each : this) @@ -147,10 +186,19 @@ default MutableSet toSet() return this.toCollection(MutableSet::empty, Collection::add); } + default MutableBag toBag() + { + return this.toCollection(MutableBag::empty, Collection::add); + } + default > R toCollection(Supplier supplier, BiConsumer addMethod) { R collection = supplier.get(); this.forEach(each -> addMethod.accept(collection, each)); return collection; } + + Bag countBy(Function function); + + Bag countByEach(Function> function); } diff --git a/deck-of-cards-kata/src/test/java/bnymellon/codekatas/deckofcards/custom/collections/MutableListTest.java b/deck-of-cards-kata/src/test/java/bnymellon/codekatas/deckofcards/custom/collections/MutableListTest.java index b01845ee..bee34215 100644 --- a/deck-of-cards-kata/src/test/java/bnymellon/codekatas/deckofcards/custom/collections/MutableListTest.java +++ b/deck-of-cards-kata/src/test/java/bnymellon/codekatas/deckofcards/custom/collections/MutableListTest.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.stream.Collector; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -412,4 +413,43 @@ public void addAllIterable() list2.addAllIterable(expected::iterator); Assertions.assertEquals(expected, list2); } + + @Test + public void countByEach() + { + MutableList> list = MutableList.of(MutableList.of(1, 2), MutableList.of(1, 2, 3)); + MutableBag counts = list.countByEach(each -> each); + Assertions.assertEquals(2, counts.getOccurrences(1)); + Assertions.assertEquals(2, counts.getOccurrences(2)); + Assertions.assertEquals(1, counts.getOccurrences(3)); + } + + @Test + public void groupByEach() + { + MutableList list = MutableList.of(1, 2, 3); + MutableListMultimap multimap = list.groupByEach(each -> IntStream.range(0, each).boxed().toList()); + Assertions.assertEquals(List.of(1, 2, 3), multimap.get(0)); + Assertions.assertEquals(List.of(2, 3), multimap.get(1)); + Assertions.assertEquals(List.of(3), multimap.get(2)); + } + + @Test + public void toBag() + { + MutableList list = MutableList.of(1, 2, 2, 3, 3, 3); + MutableBag bag = list.toBag(); + + Assertions.assertEquals(MutableBag.of(1, 2, 2, 3, 3, 3), bag); + } + + @Test + public void containsBy() + { + MutableList hasEvens = MutableList.of(1, 2, 3); + MutableList onlyOdds = MutableList.of(1, 3); + + Assertions.assertTrue(hasEvens.containsBy(each -> each % 2, 0)); + Assertions.assertFalse(onlyOdds.containsBy(each -> each % 2, 0)); + } }