From 2337e29d0bf2fcda4143d8890a3553d2ba06f93a Mon Sep 17 00:00:00 2001 From: rajatgarg Date: Tue, 8 Aug 2023 20:07:33 +0530 Subject: [PATCH 1/3] [BAEL-6708] Add Cartesian Product --- .../core-java-collections-set-2/pom.xml | 11 +++ .../cartesianproduct/CartesianProduct.java | 81 ++++++++++++++++ .../CartesianProductUnitTest.java | 93 +++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java create mode 100644 core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java diff --git a/core-java-modules/core-java-collections-set-2/pom.xml b/core-java-modules/core-java-collections-set-2/pom.xml index 680c01d8ca..b2da2ecc95 100644 --- a/core-java-modules/core-java-collections-set-2/pom.xml +++ b/core-java-modules/core-java-collections-set-2/pom.xml @@ -20,6 +20,17 @@ ${junit-platform.version} test + + org.testng + testng + 7.7.0 + test + + + com.google.guava + guava + 31.0.1-jre + diff --git a/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java b/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java new file mode 100644 index 0000000000..23d2c7aee2 --- /dev/null +++ b/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java @@ -0,0 +1,81 @@ +package com.baeldung.cartesianproduct; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.Sets; + +public class CartesianProduct { + // Responsible for calculating Cartesian Product using iterative approach. + public List> getCartesianProductIterative(List> sets) { + List> result = new ArrayList<>(); + if(sets == null || sets.isEmpty()) { + return result; + } + int totalSets = sets.size(); + int totalCombinations = 1 << totalSets; + for(int i = 0; i < totalCombinations; i++) { + List combination = new ArrayList<>(); + for(int j = 0; j < totalSets; j++) { + if (((i >> j) & 1) == 1) { + combination.add(sets.get(j).get(0)); + } else { + combination.add(sets.get(j).get(1)); + } + } + result.add(combination); + } + return result; + } + + // Responsible for calculating Cartesian Product using recursive approach. + public List> getCartesianProductRecursive(List> sets) { + List> result = new ArrayList<>(); + getCartesianProductRecursiveHelper(sets, 0, new ArrayList<>(), result); + return result; + } + + // Helper method for recursive approach + private void getCartesianProductRecursiveHelper(List> sets, int index, List current, List> result) { + if(index == sets.size()) { + result.add(new ArrayList<>(current)); + return; + } + List currentSet = sets.get(index); + for(Object element: currentSet) { + current.add(element); + getCartesianProductRecursiveHelper(sets, index+1, current, result); + current.remove(current.size() - 1); + } + } + + // Responsible for calculating Cartesian Product using streams. + public List> getCartesianProductUsingStreams(List> sets) { + return cartesianProduct(sets,0).collect(Collectors.toList()); + } + + // Helper method for streams approach. + public Stream> cartesianProduct(List> sets, int index) { + if(index == sets.size()) { + List emptyList = new ArrayList<>(); + return Stream.of(emptyList); + } + List currentSet = sets.get(index); + return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1) + .map(list -> { + List newList = new ArrayList<>(list); + newList.add(0, element); return newList; + })); + } + + // Responsible for calculating Cartesian Product using Guava library. + public List> getCartesianProductUsingGuava(List> sets) { + Set> cartesianProduct = Sets.cartesianProduct(sets); + List> cartesianList = new ArrayList<>(cartesianProduct); + return cartesianList; + } + +} diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java new file mode 100644 index 0000000000..726934e78a --- /dev/null +++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.cartesianproduct; + +import static org.testng.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.testng.annotations.Test; + +public class CartesianProductUnitTest { + private CartesianProduct cp = new CartesianProduct(); + List> sets = Arrays.asList( + Arrays.asList(10, 20), + Arrays.asList("John", "Jack"), + Arrays.asList('I', 'J') + ); + + @Test + public void shouldCalculateCartesianProductUsingStreams() { + List> expected = Arrays.asList( + Arrays.asList(10, "John", 'I'), + Arrays.asList(10, "John", 'J'), + Arrays.asList(10, "Jack", 'I'), + Arrays.asList(10, "Jack", 'J'), + Arrays.asList(20, "John", 'I'), + Arrays.asList(20, "John", 'J'), + Arrays.asList(20, "Jack", 'I'), + Arrays.asList(20, "Jack", 'J') + ); + + List> cartesianProduct = cp.getCartesianProductUsingStreams(sets); + assertEquals(expected, cartesianProduct); + } + + @Test + public void shouldCalculateCartesianProductUsingRecursion() { + List> expected = Arrays.asList( + Arrays.asList(10, "John", 'I'), + Arrays.asList(10, "John", 'J'), + Arrays.asList(10, "Jack", 'I'), + Arrays.asList(10, "Jack", 'J'), + Arrays.asList(20, "John", 'I'), + Arrays.asList(20, "John", 'J'), + Arrays.asList(20, "Jack", 'I'), + Arrays.asList(20, "Jack", 'J') + ); + + List> cartesianProduct = cp.getCartesianProductRecursive(sets); + assertEquals(expected, cartesianProduct); + } + + @Test + public void shouldCalculateCartesianProductUsingIterativeApproach() { + List> expected = Arrays.asList( + Arrays.asList(20, "Jack", 'J'), + Arrays.asList(10, "Jack", 'J'), + Arrays.asList(20, "John", 'J'), + Arrays.asList(10, "John", 'J'), + Arrays.asList(20, "Jack", 'I'), + Arrays.asList(10, "Jack", 'I'), + Arrays.asList(20, "John", 'I'), + Arrays.asList(10, "John", 'I') + ); + + List> cartesianProduct = cp.getCartesianProductIterative(sets); + assertEquals(expected, cartesianProduct); + } + + @Test + public void shouldCalculateCartesianProductUsingGuava() { + List> sets = new ArrayList<>(); + sets.add(new HashSet<>(Arrays.asList(10, 20))); + sets.add(new HashSet<>(Arrays.asList("John", "Jack"))); + sets.add(new HashSet<>(Arrays.asList('I', 'J'))); + + List> expected = Arrays.asList( + Arrays.asList(20, "John", 'I'), + Arrays.asList(20, "John", 'J'), + Arrays.asList(20, "Jack", 'I'), + Arrays.asList(20, "Jack", 'J'), + Arrays.asList(10, "John", 'I'), + Arrays.asList(10, "John", 'J'), + Arrays.asList(10, "Jack", 'I'), + Arrays.asList(10, "Jack", 'J') + ); + + List> cartesianProduct = cp.getCartesianProductUsingGuava(sets); + assertEquals(expected, cartesianProduct); + } +} \ No newline at end of file From de16d8c39cda51d5ad55d09bcaebc05c06f50bf6 Mon Sep 17 00:00:00 2001 From: rajatgarg Date: Wed, 9 Aug 2023 22:44:14 +0530 Subject: [PATCH 2/3] [BAEL-6708] Address review comments --- .../cartesianproduct/CartesianProduct.java | 6 ------ .../CartesianProductUnitTest.java | 16 ++++++++-------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java b/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java index 23d2c7aee2..d4725d74f1 100644 --- a/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java +++ b/core-java-modules/core-java-collections-set-2/src/main/java/com/baeldung/cartesianproduct/CartesianProduct.java @@ -9,7 +9,6 @@ import java.util.stream.Stream; import com.google.common.collect.Sets; public class CartesianProduct { - // Responsible for calculating Cartesian Product using iterative approach. public List> getCartesianProductIterative(List> sets) { List> result = new ArrayList<>(); if(sets == null || sets.isEmpty()) { @@ -31,14 +30,12 @@ public class CartesianProduct { return result; } - // Responsible for calculating Cartesian Product using recursive approach. public List> getCartesianProductRecursive(List> sets) { List> result = new ArrayList<>(); getCartesianProductRecursiveHelper(sets, 0, new ArrayList<>(), result); return result; } - // Helper method for recursive approach private void getCartesianProductRecursiveHelper(List> sets, int index, List current, List> result) { if(index == sets.size()) { result.add(new ArrayList<>(current)); @@ -52,12 +49,10 @@ public class CartesianProduct { } } - // Responsible for calculating Cartesian Product using streams. public List> getCartesianProductUsingStreams(List> sets) { return cartesianProduct(sets,0).collect(Collectors.toList()); } - // Helper method for streams approach. public Stream> cartesianProduct(List> sets, int index) { if(index == sets.size()) { List emptyList = new ArrayList<>(); @@ -71,7 +66,6 @@ public class CartesianProduct { })); } - // Responsible for calculating Cartesian Product using Guava library. public List> getCartesianProductUsingGuava(List> sets) { Set> cartesianProduct = Sets.cartesianProduct(sets); List> cartesianList = new ArrayList<>(cartesianProduct); diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java index 726934e78a..cc9c01fb5f 100644 --- a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java +++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/cartesianproduct/CartesianProductUnitTest.java @@ -19,7 +19,7 @@ public class CartesianProductUnitTest { ); @Test - public void shouldCalculateCartesianProductUsingStreams() { + public void whenUsingStreams_thenCalculateCartesianProduct() { List> expected = Arrays.asList( Arrays.asList(10, "John", 'I'), Arrays.asList(10, "John", 'J'), @@ -30,13 +30,13 @@ public class CartesianProductUnitTest { Arrays.asList(20, "Jack", 'I'), Arrays.asList(20, "Jack", 'J') ); - List> cartesianProduct = cp.getCartesianProductUsingStreams(sets); + assertEquals(expected, cartesianProduct); } @Test - public void shouldCalculateCartesianProductUsingRecursion() { + public void whenUsingRecursion_thenCalculateCartesianProduct() { List> expected = Arrays.asList( Arrays.asList(10, "John", 'I'), Arrays.asList(10, "John", 'J'), @@ -47,13 +47,13 @@ public class CartesianProductUnitTest { Arrays.asList(20, "Jack", 'I'), Arrays.asList(20, "Jack", 'J') ); - List> cartesianProduct = cp.getCartesianProductRecursive(sets); + assertEquals(expected, cartesianProduct); } @Test - public void shouldCalculateCartesianProductUsingIterativeApproach() { + public void whenUsingIterativeApproach_thenCalculateCartesianProduct() { List> expected = Arrays.asList( Arrays.asList(20, "Jack", 'J'), Arrays.asList(10, "Jack", 'J'), @@ -64,13 +64,13 @@ public class CartesianProductUnitTest { Arrays.asList(20, "John", 'I'), Arrays.asList(10, "John", 'I') ); - List> cartesianProduct = cp.getCartesianProductIterative(sets); + assertEquals(expected, cartesianProduct); } @Test - public void shouldCalculateCartesianProductUsingGuava() { + public void whenUsingGuava_thenCalculateCartesianProduct() { List> sets = new ArrayList<>(); sets.add(new HashSet<>(Arrays.asList(10, 20))); sets.add(new HashSet<>(Arrays.asList("John", "Jack"))); @@ -86,8 +86,8 @@ public class CartesianProductUnitTest { Arrays.asList(10, "Jack", 'I'), Arrays.asList(10, "Jack", 'J') ); - List> cartesianProduct = cp.getCartesianProductUsingGuava(sets); + assertEquals(expected, cartesianProduct); } } \ No newline at end of file From 8351c9fca326009c38d8f6bb7ffb9900437f1131 Mon Sep 17 00:00:00 2001 From: rajatgarg Date: Thu, 24 Aug 2023 08:58:53 +0530 Subject: [PATCH 3/3] [BAEL-6708] Address review comments --- core-java-modules/core-java-collections-set-2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-collections-set-2/pom.xml b/core-java-modules/core-java-collections-set-2/pom.xml index b2da2ecc95..d1a108f8bb 100644 --- a/core-java-modules/core-java-collections-set-2/pom.xml +++ b/core-java-modules/core-java-collections-set-2/pom.xml @@ -29,7 +29,7 @@ com.google.guava guava - 31.0.1-jre + 32.1.1-jre