diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 5767a5a..0718126 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -13,11 +13,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '17' - distribution: 'temurin' + java-version: '21' + distribution: 'corretto' cache: maven - name: Build with Maven run: mvn -B package --file pom.xml diff --git a/pom.xml b/pom.xml index 2623864..87bef11 100644 --- a/pom.xml +++ b/pom.xml @@ -10,8 +10,8 @@ java_stream_api - 1.8 - 1.8 + 21 + 21 UTF-8 5.13.0 diff --git a/src/main/java/java_stream_api/App.java b/src/main/java/java_stream_api/App.java index a8f4617..b387904 100644 --- a/src/main/java/java_stream_api/App.java +++ b/src/main/java/java_stream_api/App.java @@ -1,14 +1,18 @@ package java_stream_api; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Random; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; @@ -306,6 +310,389 @@ public static List userNamesSortedByLength(List users) { .collect(Collectors.toList()); } + // 51. Group a list of integers by even or odd. + public static Map> groupByEvenOdd(List intsList) { + return intsList.stream().collect(Collectors.groupingBy(n -> n % 2 == 0)); + } + + // 52. Find the second largest number in a list. + public static Optional secondLargest(List intsList) { + return intsList.stream().distinct().sorted(Comparator.reverseOrder()).skip(1).findFirst(); + } + + // 53. Get a comma-separated list of the first letters of each string. + public static String firstLettersAsString(List strList) { + return strList.stream() + .filter(s -> !s.isEmpty()) + .map(s -> s.substring(0, 1)) + .collect(Collectors.joining(",")); + } + + // 54. Partition strings into those containing digits and those not. + public static Map> partitionByContainsDigit(List strList) { + return strList.stream().collect(Collectors.partitioningBy(s -> s.matches(".*\\d.*"))); + } + + // 55. Remove palindromes from a list of strings. + public static List removePalindromes(List strList) { + return strList.stream() + .filter(s -> !s.equals(new StringBuilder(s).reverse().toString())) + .collect(Collectors.toList()); + } + + // 56. Find the most frequent string in a list. + public static Optional mostFrequentString(List strList) { + return strList.stream() + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) + .entrySet() + .stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey); + } + + // 57. Remove empty or blank strings from a list. + public static List removeBlankStrings(List strList) { + return strList.stream() + .filter(s -> s != null && !s.trim().isEmpty()) + .collect(Collectors.toList()); + } + + // 58. Double only odd numbers in a list. + public static List doubleOdds(List intsList) { + return intsList.stream().map(n -> n % 2 != 0 ? n * 2 : n).collect(Collectors.toList()); + } + + // 59. Replace negative numbers in a list with zero. + public static List replaceNegativesWithZero(List intsList) { + return intsList.stream().map(n -> n < 0 ? 0 : n).collect(Collectors.toList()); + } + + // 60. Get a map of string lengths to the count of strings of that length. + public static Map lengthToCountMap(List strList) { + return strList.stream() + .collect(Collectors.groupingBy(String::length, Collectors.counting())); + } + + // 61. Filter numbers that are perfect squares. + public static List filterPerfectSquares(List intsList) { + return intsList.stream() + .filter(n -> n >= 0 && Math.sqrt(n) % 1 == 0) + .collect(Collectors.toList()); + } + + // 62. Get the first non-repeating string in a list. + public static Optional firstNonRepeatingString(List strList) { + Map freq = + strList.stream() + .collect( + Collectors.groupingBy( + Function.identity(), + LinkedHashMap::new, + Collectors.counting())); + return freq.entrySet().stream() + .filter(e -> e.getValue() == 1) + .map(Map.Entry::getKey) + .findFirst(); + } + + // 63. Sum of all odd numbers in a list. + public static int sumOfOdds(List intsList) { + return intsList.stream().filter(n -> n % 2 != 0).mapToInt(Integer::intValue).sum(); + } + + // 64. Capitalize the first letter of each string. + public static List capitalizeFirstLetter(List strList) { + return strList.stream() + .map(s -> s.isEmpty() ? s : s.substring(0, 1).toUpperCase() + s.substring(1)) + .collect(Collectors.toList()); + } + + // 65. Find all pairs of numbers that sum to a given value. + public static List pairsThatSumTo(List intsList, int sum) { + return intsList.stream() + .flatMap( + i -> + intsList.stream() + .filter(j -> j != i && i + j == sum) + .map(j -> new int[] {i, j})) + .collect(Collectors.toList()); + } + + // 66. Map each word in a sentence to its frequency (case-insensitive). + public static Map wordFrequency(String sentence) { + return Arrays.stream(sentence.toLowerCase().split("\\s+")) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + } + + // 67. Repeat each string in a list twice (e.g., "abc" -> "abcabc"). + public static List repeatStringsTwice(List strList) { + return strList.stream().map(s -> s + s).collect(Collectors.toList()); + } + + // 68. Find unique words from a list of sentences. + public static Set uniqueWords(List sentences) { + return sentences.stream() + .flatMap(s -> Arrays.stream(s.split("\\s+"))) + .map(String::toLowerCase) + .collect(Collectors.toSet()); + } + + // 69. Sum all elements except the largest and smallest. + public static int sumExcludingExtremes(List intsList) { + return intsList.stream() + .sorted() + .skip(1) + .limit(Math.max(0, intsList.size() - 2)) + .mapToInt(Integer::intValue) + .sum(); + } + + // 70. Return the list truncated at the first occurrence of 0 (not including the 0). + public static List untilFirstZero(List intsList) { + List result = new ArrayList<>(); + for (Integer n : intsList) { + if (n == 0) break; + result.add(n); + } + return result; + } + + // 71. Group words by their first letter. + public static Map> groupByFirstChar(List strList) { + return strList.stream() + .filter(s -> !s.isEmpty()) + .collect(Collectors.groupingBy(s -> s.charAt(0))); + } + + // 72. Get the N longest strings in a list. + public static List nLongestStrings(List strList, int n) { + return strList.stream() + .sorted(Comparator.comparingInt(String::length).reversed()) + .limit(n) + .collect(Collectors.toList()); + } + + // 73. Join all numbers as a string, separated by dashes. + public static String joinNumbersWithDash(List intsList) { + return intsList.stream().map(String::valueOf).collect(Collectors.joining("-")); + } + + // 74. Swap even and odd indexed elements in a list. + public static List swapEvenOddIndexed(List list) { + List copy = new ArrayList<>(list); + for (int i = 0; i < copy.size() - 1; i += 2) { + T temp = copy.get(i); + copy.set(i, copy.get(i + 1)); + copy.set(i + 1, temp); + } + return copy; + } + + // 75. Remove all elements except the last N elements. + public static List lastNElements(List list, int n) { + return list.stream().skip(Math.max(0, list.size() - n)).collect(Collectors.toList()); + } + + // 76. Partition a list of numbers into primes and non-primes. + public static Map> partitionPrimes(List intsList) { + return intsList.stream().collect(Collectors.partitioningBy(App::isPrime)); + } + + private static boolean isPrime(int n) { + if (n < 2) return false; + for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; + return true; + } + + // 77. Map string to its reverse. + public static Map stringToReverse(List strList) { + return strList.stream() + .collect( + Collectors.toMap( + Function.identity(), + s -> new StringBuilder(s).reverse().toString())); + } + + // 78. Give a list of every prefix of each string (e.g. "abc" -> "a", "ab", "abc"). + public static List getAllPrefixes(List strList) { + return strList.stream() + .flatMap(s -> IntStream.rangeClosed(1, s.length()).mapToObj(i -> s.substring(0, i))) + .collect(Collectors.toList()); + } + + // 79. Multiply all numbers in the list. + public static int multiplyAll(List intsList) { + return intsList.stream().reduce(1, (a, b) -> a * b); + } + + // 80. Remove all vowels from all strings in a list. + public static List removeVowels(List strList) { + return strList.stream() + .map(s -> s.replaceAll("[AEIOUaeiou]", "")) + .collect(Collectors.toList()); + } + + // 81. Create a map of strings to number of vowels in each. + public static Map vowelCounts(List strList) { + return strList.stream() + .collect( + Collectors.toMap( + Function.identity(), + s -> s.chars().filter(c -> "AEIOUaeiou".indexOf(c) >= 0).count())); + } + + // 82. Count palindromes in a list. + public static long countPalindromes(List strList) { + return strList.stream() + .filter(s -> s.equals(new StringBuilder(s).reverse().toString())) + .count(); + } + + // 83. Collect the indices of all negative numbers. + public static List indicesOfNegatives(List intsList) { + return IntStream.range(0, intsList.size()) + .filter(i -> intsList.get(i) < 0) + .boxed() + .collect(Collectors.toList()); + } + + // 84. Group numbers by the sum of their digits. + public static Map> groupByDigitSum(List intsList) { + return intsList.stream() + .collect( + Collectors.groupingBy( + n -> + String.valueOf(Math.abs(n)) + .chars() + .map(Character::getNumericValue) + .sum())); + } + + // 85. For each word, repeat it as many times as its length (e.g., "hi" -> "hihi"). + public static List repeatByLength(List strList) { + return strList.stream().map(s -> s.repeat(s.length())).collect(Collectors.toList()); + } + + // 86. Check if a string list is sorted (lexicographically). + public static boolean isSorted(List strList) { + return IntStream.range(0, strList.size() - 1) + .allMatch(i -> strList.get(i).compareTo(strList.get(i + 1)) <= 0); + } + + // 87. Combine two lists into pairs (zip). + public static List> zip(List listA, List listB) { + int size = Math.min(listA.size(), listB.size()); + return IntStream.range(0, size) + .mapToObj(i -> new AbstractMap.SimpleEntry<>(listA.get(i), listB.get(i))) + .collect(Collectors.toList()); + } + + // 88. Find all substrings of a string list. + public static List allSubstrings(List strList) { + return strList.stream() + .flatMap( + s -> + IntStream.range(0, s.length()) + .boxed() + .flatMap( + i -> + IntStream.rangeClosed(i + 1, s.length()) + .mapToObj(j -> s.substring(i, j)))) + .collect(Collectors.toList()); + } + + // 89. Set negative numbers to their absolute value. + public static List setNegativesToAbsolute(List intsList) { + return intsList.stream().map(Math::abs).collect(Collectors.toList()); + } + + // 90. Find all palindromic numbers in a list. + public static List palindromicNumbers(List intsList) { + return intsList.stream() + .filter( + n -> { + String s = String.valueOf(Math.abs(n)); + return s.equals(new StringBuilder(s).reverse().toString()); + }) + .collect(Collectors.toList()); + } + + // 91. Map lowercased strings to their frequency. + public static Map lowerCaseFrequency(List strList) { + return strList.stream() + .map(String::toLowerCase) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + } + + // 92. Filter numbers that are Fibonacci numbers. + public static List filterFibonacci(List intsList) { + return intsList.stream().filter(App::isFibonacci).collect(Collectors.toList()); + } + + private static boolean isFibonacci(int n) { + long x = 5L * n * n; + return isPerfectSquare(x + 4) || isPerfectSquare(x - 4); + } + + private static boolean isPerfectSquare(long x) { + long s = (long) Math.sqrt(x); + return s * s == x; + } + + // 93. Get the difference between every consecutive element in a list. + public static List differences(List intsList) { + return IntStream.range(1, intsList.size()) + .mapToObj(i -> intsList.get(i) - intsList.get(i - 1)) + .collect(Collectors.toList()); + } + + // 94. Count the number of strings ending with a vowel. + public static long countEndsWithVowel(List strList) { + return strList.stream() + .filter(s -> !s.isEmpty() && "aeiouAEIOU".indexOf(s.charAt(s.length() - 1)) != -1) + .count(); + } + + // 95. Extract only the unique sorted words from sentences. + public static List uniqueSortedWords(List sentences) { + return sentences.stream() + .flatMap(s -> Arrays.stream(s.split("\\s+"))) + .map(String::toLowerCase) + .distinct() + .sorted() + .collect(Collectors.toList()); + } + + // 96. Find the product of all even numbers. + public static int productOfEvens(List intsList) { + return intsList.stream().filter(n -> n % 2 == 0).reduce(1, (a, b) -> a * b); + } + + // 97. Replace each string with its length in a list. + public static List stringLengths(List strList) { + return strList.stream().map(String::length).collect(Collectors.toList()); + } + + // 98. Flatten a list of integer lists into a single list. + public static List flattenIntegerLists(List> listOfLists) { + return listOfLists.stream().flatMap(Collection::stream).collect(Collectors.toList()); + } + + // 99. Remove any integers that are multiples of either 3 or 5. + public static List removeMultiplesOf3Or5(List intsList) { + return intsList.stream().filter(n -> n % 3 != 0 && n % 5 != 0).collect(Collectors.toList()); + } + + // 100. Get the longest string for each string length. + public static Map longestStringForEachLength(List strList) { + return strList.stream() + .collect( + Collectors.toMap( + String::length, + Function.identity(), + (s1, s2) -> s1.length() >= s2.length() ? s1 : s2)); + } + public static void main(String[] args) { System.out.println("== Java Stream API Methods Demo =="); diff --git a/src/test/java/java_stream_api/AppTest.java b/src/test/java/java_stream_api/AppTest.java index dc7c75f..2fec342 100644 --- a/src/test/java/java_stream_api/AppTest.java +++ b/src/test/java/java_stream_api/AppTest.java @@ -454,4 +454,443 @@ void testUserNamesSortedByLength() { void testMainRunsWithoutException() { assertDoesNotThrow(() -> App.main(new String[] {})); } + + @Test + @DisplayName("Group integers by even and odd") + void testGroupByEvenOdd() { + List input = Arrays.asList(1, 2, 3, 4); + Map> result = App.groupByEvenOdd(input); + assertEquals(Arrays.asList(2, 4), result.get(true), "Even numbers not grouped correctly"); + assertEquals(Arrays.asList(1, 3), result.get(false), "Odd numbers not grouped correctly"); + } + + @Test + @DisplayName("Find the second largest element") + void testSecondLargest() { + List input = Arrays.asList(10, 20, 30, 40); + assertEquals(Optional.of(30), App.secondLargest(input), "Second largest number incorrect"); + } + + @Test + @DisplayName("Get comma-separated list of first letters") + void testFirstLettersAsString() { + List input = Arrays.asList("apple", "banana", "carrot"); + String result = App.firstLettersAsString(input); + assertEquals("a,b,c", result, "First letters not joined correctly"); + } + + @Test + @DisplayName("Partition strings by presence of digits") + void testPartitionByContainsDigit() { + List input = Arrays.asList("abc", "a2b", "xyz3", "nope"); + Map> result = App.partitionByContainsDigit(input); + assertEquals( + Arrays.asList("a2b", "xyz3"), + result.get(true), + "Strings with digits not partitioned correctly"); + assertEquals( + Arrays.asList("abc", "nope"), + result.get(false), + "Strings without digits not partitioned correctly"); + } + + @Test + @DisplayName("Remove palindromes from a list") + void testRemovePalindromes() { + List input = Arrays.asList("madam", "apple", "kayak"); + List result = App.removePalindromes(input); + assertTrue(result.contains("apple"), "Non-palindromes were removed incorrectly"); + assertFalse(result.contains("madam"), "Palindrome was not removed"); + assertFalse(result.contains("kayak"), "Palindrome was not removed"); + } + + @Test + @DisplayName("Find most frequent string") + void testMostFrequentString() { + List input = Arrays.asList("apple", "banana", "apple", "carrot", "banana", "apple"); + Optional result = App.mostFrequentString(input); + assertEquals(Optional.of("apple"), result, "Most frequent string not correct"); + } + + @Test + @DisplayName("Remove blank and empty strings") + void testRemoveBlankStrings() { + List input = Arrays.asList("apple", "", " ", "banana"); + List result = App.removeBlankStrings(input); + assertEquals( + Arrays.asList("apple", "banana"), result, "Blank or empty strings not removed"); + } + + @Test + @DisplayName("Double odd numbers") + void testDoubleOdds() { + List input = Arrays.asList(1, 2, 3); + List result = App.doubleOdds(input); + assertEquals(Arrays.asList(2, 2, 6), result, "Odds were not doubled correctly"); + } + + @Test + @DisplayName("Replace negatives with zero") + void testReplaceNegativesWithZero() { + List input = Arrays.asList(-5, 3, 0, -1); + List result = App.replaceNegativesWithZero(input); + assertEquals( + Arrays.asList(0, 3, 0, 0), result, "Negatives not replaced with zero correctly"); + } + + @Test + @DisplayName("Map string-lengths to their count") + void testLengthToCountMap() { + List input = Arrays.asList("a", "bb", "b", "aaa"); + Map result = App.lengthToCountMap(input); + assertEquals(2L, result.get(1), "Count for length 1 incorrect"); + assertEquals(1L, result.get(2), "Count for length 2 incorrect"); + assertEquals(1L, result.get(3), "Count for length 3 incorrect"); + } + + @Test + @DisplayName("Filter perfect squares") + void testFilterPerfectSquares() { + List input = Arrays.asList(1, 2, 4, 9, 16, 20); + List result = App.filterPerfectSquares(input); + assertEquals(Arrays.asList(1, 4, 9, 16), result, "Perfect squares not filtered correctly"); + } + + @Test + @DisplayName("Find first non-repeating string") + void testFirstNonRepeatingString() { + List input = Arrays.asList("a", "b", "a", "c", "b", "d"); + Optional result = App.firstNonRepeatingString(input); + assertEquals(Optional.of("c"), result, "First non-repeating string not correct"); + } + + @Test + @DisplayName("Sum all odd numbers") + void testSumOfOdds() { + List input = Arrays.asList(1, 2, 3, 4, 5); + int sum = App.sumOfOdds(input); + assertEquals(9, sum, "Sum of odd numbers incorrect"); + } + + @Test + @DisplayName("Capitalize first letter of each string") + void testCapitalizeFirstLetter() { + List input = Arrays.asList("apple", "banana", "cat"); + List result = App.capitalizeFirstLetter(input); + assertEquals( + Arrays.asList("Apple", "Banana", "Cat"), + result, + "Strings not capitalized correctly"); + } + + @Test + @DisplayName("Find all pairs that sum to a given value") + void testPairsThatSumTo() { + List input = Arrays.asList(1, 2, 3, 4); + List result = App.pairsThatSumTo(input, 5); + assertTrue( + result.stream().anyMatch(arr -> arr[0] + arr[1] == 5), + "Pairs not found for sum correctly"); + } + + @Test + @DisplayName("Map word frequency in sentence, case-insensitive") + void testWordFrequency() { + String sentence = "apple banana apple Carrot banana carrot"; + Map result = App.wordFrequency(sentence); + assertEquals(2L, result.get("banana"), "Banana frequency incorrect"); + assertEquals(2L, result.get("carrot"), "Carrot frequency incorrect"); + } + + @Test + @DisplayName("Repeat each string twice") + void testRepeatStringsTwice() { + List input = Arrays.asList("abc", "de"); + List result = App.repeatStringsTwice(input); + assertEquals( + Arrays.asList("abcabc", "dede"), result, "Strings not repeated twice correctly"); + } + + @Test + @DisplayName("Unique words from sentences") + void testUniqueWords() { + List sentences = Arrays.asList("the cat", "the dog"); + Set result = App.uniqueWords(sentences); + assertTrue( + result.contains("cat") && result.contains("the"), + "Unique words not extracted correctly"); + } + + @Test + @DisplayName("Sum excluding largest and smallest numbers") + void testSumExcludingExtremes() { + List input = Arrays.asList(10, 20, 30, 40); + int sum = App.sumExcludingExtremes(input); + assertEquals(50, sum, "Sum excluding extremes incorrect"); + } + + @Test + @DisplayName("Elements until first zero") + void testUntilFirstZero() { + List input = Arrays.asList(1, 2, 0, 5); + List result = App.untilFirstZero(input); + assertEquals(Arrays.asList(1, 2), result, "Elements until zero not found correctly"); + } + + @Test + @DisplayName("Group words by first character") + void testGroupByFirstChar() { + List input = Arrays.asList("apple", "arm", "bat"); + Map> result = App.groupByFirstChar(input); + assertEquals( + Arrays.asList("apple", "arm"), + result.get('a'), + "Grouping by first character incorrect"); + } + + @Test + @DisplayName("Get N longest strings") + void testNLongestStrings() { + List input = Arrays.asList("a", "ab", "abc"); + List result = App.nLongestStrings(input, 2); + assertEquals( + Arrays.asList("abc", "ab"), result, "N longest strings not selected correctly"); + } + + @Test + @DisplayName("Join numbers with dash") + void testJoinNumbersWithDash() { + List input = Arrays.asList(1, 2, 3); + String result = App.joinNumbersWithDash(input); + assertEquals("1-2-3", result, "Numbers not joined with dash correctly"); + } + + @Test + @DisplayName("Swap even and odd indexed elements") + void testSwapEvenOddIndexed() { + List input = Arrays.asList("a", "b", "c", "d"); + List result = App.swapEvenOddIndexed(input); + assertEquals(Arrays.asList("b", "a", "d", "c"), result, "Even and odd indices not swapped"); + } + + @Test + @DisplayName("Return last N elements of list") + void testLastNElements() { + List input = Arrays.asList(1, 2, 3, 4, 5); + List result = App.lastNElements(input, 2); + assertEquals(Arrays.asList(4, 5), result, "Last N elements not returned correctly"); + } + + @Test + @DisplayName("Partition numbers into primes and non-primes") + void testPartitionPrimes() { + List input = Arrays.asList(2, 4, 5, 6); + Map> result = App.partitionPrimes(input); + assertEquals(Arrays.asList(2, 5), result.get(true), "Primes not partitioned correctly"); + } + + @Test + @DisplayName("Map strings to their reverse") + void testStringToReverse() { + List input = Arrays.asList("abc", "de"); + Map result = App.stringToReverse(input); + assertEquals("cba", result.get("abc"), "String reverse incorrect"); + assertEquals("ed", result.get("de"), "String reverse incorrect"); + } + + @Test + @DisplayName("Get all prefixes of each string") + void testGetAllPrefixes() { + List input = Arrays.asList("ab"); + List result = App.getAllPrefixes(input); + assertTrue(result.containsAll(Arrays.asList("a", "ab")), "String prefixes not found"); + } + + @Test + @DisplayName("Multiply all numbers in list") + void testMultiplyAll() { + List input = Arrays.asList(2, 3, 4); + int product = App.multiplyAll(input); + assertEquals(24, product, "Product not calculated correctly"); + } + + @Test + @DisplayName("Remove all vowels from strings") + void testRemoveVowels() { + List input = Arrays.asList("apple", "sky"); + List result = App.removeVowels(input); + assertEquals(Arrays.asList("ppl", "sky"), result, "Vowels not removed correctly"); + } + + @Test + @DisplayName("Count vowels in strings (per item)") + void testVowelCounts() { + List input = Arrays.asList("apple", "sky"); + Map result = App.vowelCounts(input); + assertEquals(2L, result.get("apple"), "Vowel count of 'apple' incorrect"); + assertEquals(0L, result.get("sky"), "Vowel count of 'sky' incorrect"); + } + + @Test + @DisplayName("Count the number of palindromes") + void testCountPalindromes() { + List input = Arrays.asList("madam", "abba", "apple"); + long count = App.countPalindromes(input); + assertEquals(2L, count, "Number of palindromes incorrect"); + } + + @Test + @DisplayName("Collect indices of negative numbers") + void testIndicesOfNegatives() { + List input = Arrays.asList(-1, 2, -3, 4); + List result = App.indicesOfNegatives(input); + assertEquals(Arrays.asList(0, 2), result, "Indices of negatives incorrect"); + } + + @Test + @DisplayName("Group numbers by digit sum") + void testGroupByDigitSum() { + List input = Arrays.asList(12, 21, 3, 30); + Map> result = App.groupByDigitSum(input); + assertTrue(result.get(3).contains(3), "Digit sum grouping incorrect - 3"); + assertTrue( + result.get(3).contains(12) || result.get(3).contains(21), + "Digit sum grouping incorrect - 12/21"); + } + + @Test + @DisplayName("Repeat each word by its length") + void testRepeatByLength() { + List input = Arrays.asList("hi", "a"); + List result = App.repeatByLength(input); + assertEquals(Arrays.asList("hihi", "a"), result, "Repeat by length incorrect"); + } + + @Test + @DisplayName("Check if string list is sorted") + void testIsSorted() { + List input = Arrays.asList("a", "b", "c"); + assertTrue(App.isSorted(input), "List should be sorted"); + List input2 = Arrays.asList("b", "a", "c"); + assertFalse(App.isSorted(input2), "List should be unsorted"); + } + + @Test + @DisplayName("Zip two lists into entry pairs") + void testZip() { + List l1 = Arrays.asList("a", "b"); + List l2 = Arrays.asList(1, 2); + List> result = App.zip(l1, l2); + assertEquals("a", result.get(0).getKey(), "First element of zipped pair incorrect"); + assertEquals(1, result.get(0).getValue(), "Second element of zipped pair incorrect"); + } + + @Test + @DisplayName("Get all substrings from string list") + void testAllSubstrings() { + List input = Arrays.asList("ab"); + List result = App.allSubstrings(input); + assertTrue(result.containsAll(Arrays.asList("a", "ab", "b")), "All substrings not found"); + } + + @Test + @DisplayName("Set all numbers to absolute value") + void testSetNegativesToAbsolute() { + List input = Arrays.asList(-1, 2, -3); + List result = App.setNegativesToAbsolute(input); + assertEquals(Arrays.asList(1, 2, 3), result, "Negative numbers not converted to absolute"); + } + + @Test + @DisplayName("Find all palindromic numbers") + void testPalindromicNumbers() { + List input = Arrays.asList(121, 12, 22, 132); + List result = App.palindromicNumbers(input); + assertTrue(result.containsAll(Arrays.asList(121, 22)), "Palindromic numbers not found"); + } + + @Test + @DisplayName("Map lowercased strings to their frequency") + void testLowerCaseFrequency() { + List input = Arrays.asList("a", "A", "b"); + Map result = App.lowerCaseFrequency(input); + assertEquals(2L, result.get("a"), "Lowercase frequency incorrect"); + } + + @Test + @DisplayName("Filter Fibonacci numbers") + void testFilterFibonacci() { + List input = Arrays.asList(2, 3, 5, 6); + List result = App.filterFibonacci(input); + assertTrue(result.containsAll(Arrays.asList(2, 3, 5)), "Fibonacci numbers not filtered"); + assertFalse(result.contains(6), "Non-Fibonacci number included"); + } + + @Test + @DisplayName("Get all differences between consecutive numbers") + void testDifferences() { + List input = Arrays.asList(1, 3, 6, 10); + List result = App.differences(input); + assertEquals( + Arrays.asList(2, 3, 4), + result, + "Differences between consecutive elements incorrect"); + } + + @Test + @DisplayName("Count how many strings end with a vowel") + void testCountEndsWithVowel() { + List input = Arrays.asList("apple", "banana", "dog"); + long count = App.countEndsWithVowel(input); + assertEquals(2L, count, "Strings ending with vowel counted incorrectly"); + } + + @Test + @DisplayName("Get unique sorted words out of sentences") + void testUniqueSortedWords() { + List input = Arrays.asList("the dog", "The Cat"); + List result = App.uniqueSortedWords(input); + assertEquals(Arrays.asList("cat", "dog", "the"), result, "Unique sorted words not found"); + } + + @Test + @DisplayName("Get product of all even numbers") + void testProductOfEvens() { + List input = Arrays.asList(2, 3, 4, 5); + int result = App.productOfEvens(input); + assertEquals(8, result, "Product of even numbers incorrect"); + } + + @Test + @DisplayName("Replace each string by its length") + void testStringLengths() { + List input = Arrays.asList("a", "abc"); + List result = App.stringLengths(input); + assertEquals(Arrays.asList(1, 3), result, "String lengths not mapped correctly"); + } + + @Test + @DisplayName("Flatten a list of integer lists") + void testFlattenIntegerLists() { + List> input = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3)); + List result = App.flattenIntegerLists(input); + assertEquals(Arrays.asList(1, 2, 3), result, "Integer lists not flattened"); + } + + @Test + @DisplayName("Remove multiples of 3 or 5") + void testRemoveMultiplesOf3Or5() { + List input = Arrays.asList(3, 5, 7, 9, 10, 11); + List result = App.removeMultiplesOf3Or5(input); + assertEquals(Arrays.asList(7, 11), result, "Multiples of 3 or 5 not removed"); + } + + @Test + @DisplayName("Longest string for each string length") + void testLongestStringForEachLength() { + List input = Arrays.asList("a", "bb", "cc", "bbb"); + Map result = App.longestStringForEachLength(input); + assertEquals("a", result.get(1), "Longest string for length 1 incorrect"); + assertEquals("bbb", result.get(3), "Longest string for length 3 incorrect"); + } }