├── .travis.yml ├── src ├── main │ └── java │ │ ├── xyz │ │ └── ivan │ │ │ └── snippet │ │ │ ├── performance │ │ │ ├── PerformanceStrategy.java │ │ │ ├── SimpleExecutionTimeStrategy.java │ │ │ └── MultiTimesStrategy.java │ │ │ └── array │ │ │ ├── InitialArrayWithValuesMain.java │ │ │ ├── InitialMain.java │ │ │ ├── InitialArrayWithRangeMain.java │ │ │ ├── DistinctValuesOfArrayMain.java │ │ │ ├── IndexOfMain.java │ │ │ ├── DropRightMain.java │ │ │ ├── CountOccurrenceMain.java │ │ │ ├── FlattenMain.java │ │ │ ├── GroupByMain.java │ │ │ ├── IsSortedMain.java │ │ │ ├── EveryNthMain.java │ │ │ ├── ConcatMain.java │ │ │ ├── WordLengthExtractor.java │ │ │ ├── DropElementsMain.java │ │ │ ├── IntersectionMain.java │ │ │ ├── DeepFlattenMain.java │ │ │ ├── LastIndexOfMain.java │ │ │ ├── DifferenceWithMain.java │ │ │ ├── FlattenDepthMain.java │ │ │ ├── DifferenceMain.java │ │ │ ├── FilterNonUniqueMain.java │ │ │ └── ChunkMain.java │ │ └── snippets │ │ └── Snippets.java └── test │ └── java │ └── snippets │ └── SnippetsTests.java ├── pom.xml ├── .gitignore ├── LICENSE └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | notifications: 7 | email: false 8 | 9 | sudo: false 10 | 11 | before_install: 12 | - export TZ='Asia/Shanghai' -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/performance/PerformanceStrategy.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.performance; 2 | 3 | public interface PerformanceStrategy { 4 | long execute(Runnable runnable); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/performance/SimpleExecutionTimeStrategy.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.performance; 2 | 3 | public class SimpleExecutionTimeStrategy implements PerformanceStrategy{ 4 | @Override 5 | public long execute(Runnable runnable) { 6 | long startTime = System.nanoTime(); 7 | runnable.run(); 8 | long endTime = System.nanoTime(); 9 | return endTime - startTime; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/InitialArrayWithValuesMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | public class InitialArrayWithValuesMain { 7 | public static void main(String[] args) { 8 | Arrays.stream(initializeArrayWithValues(5, 2)).forEach(System.out::println); 9 | } 10 | 11 | private static int[] initializeArrayWithValues(int n, int value){ 12 | return IntStream.generate(()->value).limit(n).toArray(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/InitialMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * 返回数组中除去最后一个的所有元素。 8 | */ 9 | public class InitialMain { 10 | public static void main(String[] args) { 11 | Object[] array = IntStream.of(1, 2, 3).boxed().toArray(); 12 | Arrays.stream(initial(array)).forEach(System.out::println); 13 | } 14 | 15 | private static T[] initial(T[] elements){ 16 | return Arrays.copyOfRange(elements, 0, elements.length - 1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/InitialArrayWithRangeMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | 5 | // 初始化一个数组,该数组包含在指定范围内的数字,传入 start 和 end。 6 | public class InitialArrayWithRangeMain { 7 | public static void main(String[] args) { 8 | Integer[] array = new Integer[]{1,2,3}; 9 | Arrays.stream(initialArrayWithRange(array,0,1)).forEach(System.out::println); 10 | } 11 | private static T[] initialArrayWithRange(T[] elements, int begin, int end){ 12 | return Arrays.copyOfRange(elements,begin,end+1); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DistinctValuesOfArrayMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * 数组去重 8 | */ 9 | public class DistinctValuesOfArrayMain { 10 | public static void main(String[] args) { 11 | int[] array = IntStream.of(1, 1, 2, 3, 3, 2).toArray(); 12 | Arrays.stream(distinctValuesOfArray(array)).forEach(System.out::println); 13 | } 14 | 15 | private static int[] distinctValuesOfArray(int[] arr){ 16 | return Arrays.stream(arr).distinct().toArray(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/performance/MultiTimesStrategy.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.performance; 2 | 3 | public class MultiTimesStrategy implements PerformanceStrategy{ 4 | private int times; 5 | 6 | public MultiTimesStrategy(int times) { 7 | this.times = times; 8 | } 9 | 10 | @Override 11 | public long execute(Runnable runnable) { 12 | long startTime = System.nanoTime(); 13 | for (int i = 0; i < times; i++) { 14 | runnable.run(); 15 | } 16 | long endTime = System.nanoTime(); 17 | return endTime - startTime; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/IndexOfMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | // 查找数组中元素的索引,在不存在元素的情况下返回-1。 6 | public class IndexOfMain { 7 | public static void main(String[] args) { 8 | int[] elements = IntStream.of(1, 2, 3, 4, 6).toArray(); 9 | System.out.println(indexOf(elements, 5)); 10 | } 11 | 12 | private static int indexOf(int[] elements, int element){ 13 | return IntStream.range(0, elements.length) 14 | .filter(i -> elements[i] == element) 15 | .findFirst() 16 | .orElse(-1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DropRightMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | public class DropRightMain { 7 | public static void main(String[] args) { 8 | Arrays.stream(dropRight(IntStream.of(1, 2, 3).toArray(), 1)).forEach(System.out::println); 9 | } 10 | 11 | private static int[] dropRight(int[] elements, int n){ 12 | if(n < 0){ 13 | throw new IllegalArgumentException("n is less than 0"); 14 | } 15 | return n < elements.length ? Arrays.copyOfRange(elements, 0, elements.length - n) 16 | : new int[0]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/CountOccurrenceMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * 计算数组中的数出现的次数 8 | */ 9 | public class CountOccurrenceMain { 10 | public static void main(String[] args) { 11 | Integer[] arr = Stream.of(1, 1, 2, 3, 3).toArray(i -> new Integer[i]); 12 | long l = countOccurrence(arr, 4); 13 | System.out.println(l); 14 | } 15 | 16 | private static long countOccurrence(Integer[] arr, Integer value){ 17 | return Arrays.stream(arr) 18 | .parallel() // 通过并行不一定能够提升性能 19 | .filter(num -> num == value) 20 | .count(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/FlattenMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * 使得数组扁平 8 | */ 9 | public class FlattenMain { 10 | public static void main(String[] args) { 11 | Object[] array = new Object[]{ new int[]{1, 2, 3}, new int[]{4, 5, 6} , 7, 8, 9}; 12 | Arrays.stream(flatten(array)).forEach(System.out::println); 13 | } 14 | 15 | private static int[] flatten(Object [] array){ 16 | return Arrays.stream(array) 17 | .flatMapToInt(el -> el instanceof int[] ? Arrays.stream((int [])el) : IntStream.of((int) el)) 18 | .toArray(); 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/GroupByMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.function.Function; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * 根据给定函数对数组元素进行分组。 11 | */ 12 | public class GroupByMain { 13 | public static void main(String[] args) { 14 | String[] array = new String[]{"a","b","c","ab","bc","abc"}; 15 | groupBy(array, element->element.contains("a")).entrySet().forEach(System.out::println); 16 | } 17 | private static Map> groupBy(T[] elements, Function func){ 18 | return Arrays.stream(elements).collect(Collectors.groupingBy(func)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/IsSortedMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | public class IsSortedMain { 4 | public static void main(String[] args) { 5 | Integer[] array = new Integer[]{1, 2, 3, 4, 1}; 6 | int sorted = isSorted(array); 7 | System.out.println(sorted); 8 | } 9 | public static > int isSorted(T[] arr) { 10 | final int direction = arr[0].compareTo(arr[1]) < 0 ? 1 : -1; 11 | for (int i = 0; i < arr.length; i++) { 12 | T val = arr[i]; 13 | if (i == arr.length - 1) return direction; 14 | else if ((val.compareTo(arr[i + 1]) * direction > 0)) return 0; 15 | } 16 | return direction; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/EveryNthMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | // 返回数组中的每个第n个元素。 7 | // egg: 1,2,3,4,5,6 nth=1 res:1,2,3,4,5,6 8 | // egg: 1,2,3,4,5,6 nth=2 res:2,4,6 9 | // egg: 1,2,3,4,5,6 nth=3 res:3,6 10 | 11 | public class EveryNthMain { 12 | public static void main(String[] args) { 13 | Arrays.stream(everyNth(IntStream.of(1,2,3,4,5,6).toArray(), 4)).forEach(System.out::println); 14 | } 15 | public static int[] everyNth(int[] elements, int nth) { 16 | return IntStream.range(0, elements.length) 17 | .filter(i -> (i + 1) % nth == 0) 18 | .map(i -> elements[i]) 19 | .toArray(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/ConcatMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * toArray的参数是当前流的长度,toArray做的事就是声明要转成的数组的类型 8 | */ 9 | public class ConcatMain { 10 | public static void main(String[] args) { 11 | Integer[] first = Stream.of(1, 2, 3).toArray(i -> new Integer[i]); 12 | Integer[] second = Stream.of(4, 5, 6).toArray(Integer[]::new); 13 | Stream.of(concat(first, second)).forEach(System.out::println); 14 | } 15 | 16 | public static T[] concat(T[] first, T[] second){ 17 | return Stream.concat(Stream.of(first), Stream.of(second)) 18 | .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/WordLengthExtractor.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | 5 | public class WordLengthExtractor { 6 | public static int[] extractWordLengths(String[] sentences) { 7 | // 实现代码 8 | return Arrays.stream(sentences) 9 | .flatMap(str -> Arrays.stream(str.split(" "))) 10 | .mapToInt(String::length) 11 | .toArray(); 12 | } 13 | 14 | public static void main(String[] args) { 15 | String[] sentences = { 16 | "Hello world", 17 | "Java programming", 18 | "FlatMap is powerful" 19 | }; 20 | int[] lengths = extractWordLengths(sentences); 21 | System.out.println(Arrays.toString(lengths)); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DropElementsMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.function.IntPredicate; 5 | import java.util.stream.IntStream; 6 | // 移除数组中的元素,直到传递的函数返回true为止。返回数组中的其余元素。 7 | public class DropElementsMain { 8 | public static void main(String[] args) { 9 | int[] elements = IntStream.of(0, 2, 3, 1, 2, 3).toArray(); 10 | Arrays.stream(dropElements(elements, element -> Integer.compare(element, 1) == 0)).forEach(System.out::println); 11 | } 12 | 13 | private static int[] dropElements(int[] elements, IntPredicate predicate){ 14 | while(elements.length > 0 && !predicate.test(elements[0])){ 15 | elements = Arrays.copyOfRange(elements, 1, elements.length); 16 | } 17 | return elements; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/IntersectionMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.IntStream; 7 | 8 | // 求两个集合的交集 9 | public class IntersectionMain { 10 | public static void main(String[] args) { 11 | int[] first = IntStream.of(1, 2, 3, 4, 5).toArray(); 12 | int[] second = IntStream.of(1, 3, 5,7,9).toArray(); 13 | Arrays.stream(intersection(first,second)).forEach(System.out::println); 14 | } 15 | 16 | private static int[] intersection(int[] first, int[] second){ 17 | Set set = Arrays.stream(first).boxed().collect(Collectors.toSet()); 18 | return Arrays.stream(second) 19 | .filter(set::contains) 20 | .toArray(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DeepFlattenMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * 使用递归实现数组扁平化 8 | */ 9 | public class DeepFlattenMain { 10 | public static void main(String[] args) { 11 | Object[][][] objs = new Object[][][]{{{1}, {2}, {3}},{{4}, {5}, {6}}}; 12 | Arrays.stream(deepFlatten(objs)).forEach(System.out::println); 13 | } 14 | 15 | public static int[] deepFlatten(Object[] input){ 16 | return Arrays.stream(input) 17 | .flatMapToInt(o -> { 18 | if(o instanceof Object[]){ 19 | return Arrays.stream(deepFlatten((Object[]) o)); 20 | } 21 | return IntStream.of((Integer) o); 22 | }).toArray(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/LastIndexOfMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | public class LastIndexOfMain { 6 | public static void main(String[] args) { 7 | int[] elements = IntStream.of(1, 2, 3, 4, 6, 3).toArray(); 8 | System.out.println(lastIndexOf(elements, 3)); 9 | } 10 | 11 | private static int lastIndexOf(int[] elements, int element){ 12 | // 第一种实现方式 13 | // return IntStream.range(0, elements.length) 14 | // .map(i -> elements.length - 1 - i) 15 | // .filter(i -> elements[i] == element) 16 | // .findFirst() 17 | // .orElse(-1); 18 | // 第二种实现方式 19 | return IntStream.iterate(elements.length - 1, i -> i - 1) 20 | .limit(elements.length) 21 | .filter(i -> elements[i] == element) 22 | .findFirst() 23 | .orElse(-1); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DifferenceWithMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.function.IntBinaryOperator; 5 | import java.util.stream.IntStream; 6 | 7 | /** 8 | * 使用IntBinaryOperator实现DifferenceWith,而不是set 9 | */ 10 | public class DifferenceWithMain { 11 | public static void main(String[] args) { 12 | int[] first = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toArray(); 13 | int[] second = IntStream.of(2, 4, 6, 8, 10, 12).toArray(); 14 | Arrays.stream(differenceWith(first, second, (a, b) -> a - b)).forEach(System.out::println); 15 | } 16 | 17 | public static int[] differenceWith(int[] first, int[] second, IntBinaryOperator comparator){ 18 | return Arrays.stream(first) 19 | .filter(a -> 20 | Arrays.stream(second) 21 | .noneMatch(b -> comparator.applyAsInt(a, b) == 0) 22 | ).toArray(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/FlattenDepthMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * flatMap中的返回值只能返回stream 8 | * 同理,flatMapToInt中的返回值只能返回IntStream 9 | */ 10 | public class FlattenDepthMain { 11 | public static void main(String[] args) { 12 | int[][][] array = new int[][][]{ 13 | { {1}, {2}, {3} }, 14 | { {4}, {5}, {6} }, 15 | }; 16 | Arrays.stream(flattenDepth(array, 0)).forEach(System.out::println); 17 | } 18 | 19 | private static Object[] flattenDepth(Object[] elements, int depth){ 20 | if (depth == 0) { 21 | return elements; 22 | } 23 | return Arrays.stream(elements). 24 | flatMap(el -> 25 | el instanceof Object[] ? Arrays.stream(flattenDepth(elements, depth - 1)) 26 | : Stream.of(el) 27 | ).toArray(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/DifferenceMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.IntStream; 7 | 8 | /** 9 | * 从 b 中创建一个集合,然后在 a 上使用 Arrays.stream().filter() 只保留 b 中不包含的值。 10 | */ 11 | public class DifferenceMain { 12 | public static void main(String[] args) { 13 | int[] a = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toArray(); 14 | int[] b = IntStream.of( 2, 4, 6, 8, 10).toArray(); 15 | Arrays.stream(difference(a, b)).forEach(System.out::println); 16 | } 17 | 18 | public static int[] difference(int[] first, int[] second){ 19 | Set set = Arrays.stream(second) 20 | .boxed() // 将基本类型 int 转换为对象类型 Integer,因为集合 Set 需要对象类型。 21 | .collect(Collectors.toSet()); 22 | return Arrays.stream(first) 23 | .filter(v -> !set.contains(v)) 24 | .toArray(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/FilterNonUniqueMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | public class FilterNonUniqueMain { 7 | public static void main(String[] args) { 8 | int[] array = IntStream.of(1, 1, 2, 3, 4).toArray(); 9 | Arrays.stream(filterNonUnique(array)).forEach(System.out::println); 10 | } 11 | 12 | private static int[] filterNonUnique(int[] elements){ 13 | return Arrays.stream(elements) 14 | .filter(element -> indexOf(elements, element) != lastIndexOf(elements, element)) 15 | .distinct() 16 | .toArray(); 17 | } 18 | 19 | private static int indexOf(int[] elements, int element){ 20 | return IntStream.range(0, elements.length) 21 | .filter(i -> elements[i] == element) 22 | .findFirst() 23 | .orElse(-1); 24 | } 25 | 26 | private static int lastIndexOf(int[] elements, int element){ 27 | return IntStream.iterate(elements.length - 1, i -> i - 1) 28 | .limit(elements.length) 29 | .filter(i -> elements[i] == element) 30 | .findFirst() 31 | .orElse(-1); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/xyz/ivan/snippet/array/ChunkMain.java: -------------------------------------------------------------------------------- 1 | package xyz.ivan.snippet.array; 2 | 3 | import xyz.ivan.snippet.performance.MultiTimesStrategy; 4 | import xyz.ivan.snippet.performance.PerformanceStrategy; 5 | 6 | import java.util.Arrays; 7 | import java.util.stream.IntStream; 8 | 9 | public class ChunkMain { 10 | 11 | private static PerformanceStrategy strategy = new MultiTimesStrategy(10); 12 | 13 | public static void main(String[] args) { 14 | int[] arr = {1, 2, 3, 4, 5}; 15 | int size = 2; 16 | long nanoTime = strategy.execute(() -> { 17 | chunk1(arr, size); 18 | }); 19 | System.out.println(nanoTime); 20 | nanoTime = strategy.execute(() ->{ 21 | chunk(arr, size); 22 | }); 23 | System.out.println(nanoTime); 24 | } 25 | 26 | 27 | // 将数组切割成特定大小的数组 28 | private static int[][] chunk(int[] arr, int size){ 29 | return IntStream.iterate(0, i -> i + size) 30 | .limit((long) Math.ceil((double) arr.length / size)) 31 | .mapToObj(cur -> Arrays.copyOfRange(arr, cur, cur + size > arr.length ? arr.length : cur + size)) 32 | .toArray(int[][]::new); 33 | } 34 | 35 | 36 | // 没有使用流的高性能的做法 37 | private static int[][] chunk1(int[] arr, int size) { 38 | int numChunks = (int) Math.ceil((double) arr.length / size); 39 | int[][] result = new int[numChunks][]; 40 | 41 | for (int i = 0; i < numChunks; i++) { 42 | int start = i * size; 43 | int length = Math.min(size, arr.length - start); 44 | result[i] = new int[length]; 45 | System.arraycopy(arr, start, result[i], 0, length); 46 | } 47 | 48 | return result; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.github.biezhi 8 | 30-seconds-of-java8 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 1.8 13 | 1.8 14 | 4.12 15 | 3.8.0 16 | 17 | 18 | 19 | 20 | junit 21 | junit 22 | ${junit.version} 23 | test 24 | 25 | 26 | org.assertj 27 | assertj-core 28 | ${assertj.version} 29 | test 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-surefire-plugin 38 | 2.20 39 | 40 | 41 | **/Test*.java 42 | **/*Test.java 43 | **/*Tests.java 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Maven template 3 | target/ 4 | .idea/ 5 | pom.xml.tag 6 | pom.xml.releaseBackup 7 | pom.xml.versionsBackup 8 | pom.xml.next 9 | release.properties 10 | dependency-reduced-pom.xml 11 | buildNumber.properties 12 | .mvn/timing.properties 13 | 14 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 15 | !/.mvn/wrapper/maven-wrapper.jar 16 | ### JetBrains template 17 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 18 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 19 | 20 | # User-specific stuff: 21 | .idea/**/workspace.xml 22 | .idea/**/tasks.xml 23 | .idea/dictionaries 24 | 25 | # Sensitive or high-churn files: 26 | .idea/**/dataSources/ 27 | .idea/**/dataSources.ids 28 | .idea/**/dataSources.xml 29 | .idea/**/dataSources.local.xml 30 | .idea/**/sqlDataSources.xml 31 | .idea/**/dynamic.xml 32 | .idea/**/uiDesigner.xml 33 | 34 | # Gradle: 35 | .idea/**/gradle.xml 36 | .idea/**/libraries 37 | 38 | # CMake 39 | cmake-build-debug/ 40 | 41 | # Mongo Explorer plugin: 42 | .idea/**/mongoSettings.xml 43 | 44 | ## File-based project format: 45 | *.iws 46 | 47 | ## Plugin-specific files: 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # Crashlytics plugin (for Android Studio and IntelliJ) 62 | com_crashlytics_export_strings.xml 63 | crashlytics.properties 64 | crashlytics-build.properties 65 | fabric.properties 66 | ### Eclipse template 67 | 68 | .metadata 69 | bin/ 70 | tmp/ 71 | *.tmp 72 | *.bak 73 | *.swp 74 | *~.nib 75 | local.properties 76 | .settings/ 77 | .loadpath 78 | .recommenders 79 | 80 | # External tool builders 81 | .externalToolBuilders/ 82 | 83 | # Locally stored "Eclipse launch configurations" 84 | *.launch 85 | 86 | # PyDev specific (Python IDE for Eclipse) 87 | *.pydevproject 88 | 89 | # CDT-specific (C/C++ Development Tooling) 90 | .cproject 91 | 92 | # Java annotation processor (APT) 93 | .factorypath 94 | 95 | # PDT-specific (PHP Development Tools) 96 | .buildpath 97 | 98 | # sbteclipse plugin 99 | .target 100 | 101 | # Tern plugin 102 | .tern-project 103 | 104 | # TeXlipse plugin 105 | .texlipse 106 | 107 | # STS (Spring Tool Suite) 108 | .springBeans 109 | 110 | # Code Recommenders 111 | .recommenders/ 112 | 113 | # Scala IDE specific (Scala & Java development for Eclipse) 114 | .cache-main 115 | .scala_dependencies 116 | .worksheet 117 | .vscode 118 | 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | -------------------------------------------------------------------------------- /src/test/java/snippets/SnippetsTests.java: -------------------------------------------------------------------------------- 1 | package snippets; 2 | 3 | import java.util.AbstractMap.SimpleEntry; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.OptionalInt; 10 | import java.util.stream.IntStream; 11 | 12 | import org.junit.Test; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | public class SnippetsTests { 17 | 18 | @Test 19 | public void gcd_of_array_containing_1_to_5_is_1() throws Exception { 20 | OptionalInt gcd = Snippets.gcd(new int[]{1, 2, 3, 4, 5}); 21 | assertThat(gcd).isNotEmpty(); 22 | assertThat(gcd).hasValue(1); 23 | } 24 | 25 | @Test 26 | public void gcd_of_array_containing_4_8_and_12_is_4() throws Exception { 27 | OptionalInt gcd = Snippets.gcd(new int[]{4, 8, 12}); 28 | assertThat(gcd).isNotEmpty(); 29 | assertThat(gcd).hasValue(4); 30 | } 31 | 32 | @Test 33 | public void lcm_of_array_containing_1_to_5_is_60() throws Exception { 34 | OptionalInt lcm = Snippets.lcm(new int[]{1, 2, 3, 4, 5}); 35 | assertThat(lcm).isNotEmpty(); 36 | assertThat(lcm).hasValue(60); 37 | } 38 | 39 | @Test 40 | public void lcm_of_array_containing_4_8_and_12_is_24() throws Exception { 41 | OptionalInt lcm = Snippets.lcm(new int[]{4, 8, 12}); 42 | assertThat(lcm).isNotEmpty(); 43 | assertThat(lcm).hasValue(24); 44 | } 45 | 46 | @Test 47 | public void max_of_array_containing_10_1_and_5_is_10() throws Exception { 48 | OptionalInt max = Snippets.arrayMax(new int[]{10, 1, 5}); 49 | assertThat(max).hasValue(10); 50 | } 51 | 52 | @Test 53 | public void min_of_array_containing_10_1_and_5_is_10() throws Exception { 54 | OptionalInt min = Snippets.arrayMin(new int[]{10, 1, 5}); 55 | assertThat(min).hasValue(1); 56 | } 57 | 58 | @Test 59 | public void chunk_breaks_input_array__with_odd_length() throws Exception { 60 | int[][] chunks = Snippets.chunk(new int[]{1, 2, 3, 4, 5}, 2); 61 | assertThat(chunks) 62 | .containsExactly( 63 | new int[]{1, 2}, 64 | new int[]{3, 4}, 65 | new int[]{5} 66 | ); 67 | } 68 | 69 | @Test 70 | public void chunk_breaks_input_array__with_event_length() throws Exception { 71 | int[][] chunks = Snippets.chunk(new int[]{1, 2, 3, 4, 5, 6}, 2); 72 | assertThat(chunks) 73 | .containsExactly( 74 | new int[]{1, 2}, 75 | new int[]{3, 4}, 76 | new int[]{5, 6} 77 | ); 78 | } 79 | 80 | @Test 81 | public void countOccurrences_counts_occurrences_of_a_value() throws Exception { 82 | long count = Snippets.countOccurrences(new int[]{1, 1, 2, 1, 2, 3}, 1); 83 | assertThat(count).isEqualTo(3); 84 | } 85 | 86 | @Test 87 | public void deepFlatten_flatten_a_deeply_nested_array() throws Exception { 88 | int[] flatten = Snippets.deepFlatten( 89 | new Object[]{1, new Object[]{2}, new Object[]{3, 4, 5}} 90 | ); 91 | 92 | assertThat(flatten).isEqualTo(new int[]{1, 2, 3, 4, 5}); 93 | } 94 | 95 | @Test 96 | public void difference_between_array_with_1_2_3_and_array_with_1_2_4_is_3() throws Exception { 97 | int[] difference = Snippets.difference(new int[]{1, 2, 3}, new int[]{1, 2, 4}); 98 | assertThat(difference).isEqualTo(new int[]{3}); 99 | } 100 | 101 | @Test 102 | public void difference_between_array_with_1_2_3_and_array_with_1_2_3_is_empty_array() throws Exception { 103 | int[] difference = Snippets.difference(new int[]{1, 2, 3}, new int[]{1, 2, 3}); 104 | assertThat(difference).isEmpty(); 105 | } 106 | 107 | @Test 108 | public void differenceWith_return_all_squares_that_do_not_exist_in_second() throws Exception { 109 | int[] difference = Snippets.differenceWith( 110 | new int[]{1, 4, 9, 16, 25}, 111 | new int[]{1, 2, 3, 6, 7}, 112 | (o1, o2) -> o1 - (o2 * o2) 113 | ); 114 | 115 | assertThat(difference).isEqualTo(new int[]{16, 25}); 116 | } 117 | 118 | @Test 119 | public void differenceWith_returns_empty_array_when_two_arrays_are_equal_as_per_comparison_operation() throws Exception { 120 | int[] difference = Snippets.differenceWith( 121 | new int[]{1, 2, 3}, 122 | new int[]{1, 2, 3}, 123 | (o1, o2) -> o1 - o2 124 | ); 125 | 126 | assertThat(difference).isEmpty(); 127 | } 128 | 129 | @Test 130 | public void differenceWith_returns_first_array_when_elements_in_second_array_are_not_comparable_as_per_comparison_operation() throws Exception { 131 | int[] difference = Snippets.differenceWith( 132 | new int[]{1, 2, 3}, 133 | new int[]{10, 11, 12}, 134 | (o1, o2) -> o1 - o2 135 | ); 136 | 137 | assertThat(difference).isEqualTo(new int[]{1, 2, 3}); 138 | } 139 | 140 | @Test 141 | public void distinct_remove_all_duplicate_values_from_an_array() throws Exception { 142 | int[] distinct = Snippets.distinctValuesOfArray(new int[]{1, 2, 2, 3, 4, 4, 5}); 143 | assertThat(distinct).isEqualTo(new int[]{1, 2, 3, 4, 5}); 144 | } 145 | 146 | @Test 147 | public void drop_elements_less_than_3() throws Exception { 148 | int[] elements = Snippets.dropElements(new int[]{1, 2, 3, 4}, i -> i >= 3); 149 | assertThat(elements).isEqualTo(new int[]{3, 4}); 150 | } 151 | 152 | @Test 153 | public void drop_elements_returns_empty_array_when_no_element_match_the_condition() throws Exception { 154 | int[] elements = Snippets.dropElements(new int[]{1, 2, 3, 4}, i -> i < 1); 155 | assertThat(elements).isEmpty(); 156 | } 157 | 158 | @Test 159 | public void drop_elements__return_all_elements_when_all_elements_match_the_condition() throws Exception { 160 | int[] elements = Snippets.dropElements(new int[]{1, 2, 3, 4}, i -> i <= 4); 161 | assertThat(elements).isEqualTo(new int[]{1, 2, 3, 4}); 162 | } 163 | 164 | @Test 165 | public void dropRight_remove_n_elements_from_right() throws Exception { 166 | int[] elements = Snippets.dropRight(new int[]{1, 2, 3}, 1); 167 | assertThat(elements).isEqualTo(new int[]{1, 2}); 168 | 169 | elements = Snippets.dropRight(new int[]{1, 2, 3}, 2); 170 | assertThat(elements).isEqualTo(new int[]{1}); 171 | 172 | elements = Snippets.dropRight(new int[]{1, 2, 3}, 3); 173 | assertThat(elements).isEmpty(); 174 | 175 | elements = Snippets.dropRight(new int[]{1, 2, 3}, 42); 176 | assertThat(elements).isEmpty(); 177 | } 178 | 179 | @Test 180 | public void everyNth_return_every_2nd_element() throws Exception { 181 | int[] elements = Snippets.everyNth(new int[]{1, 2, 3, 4, 5, 6}, 2); 182 | assertThat(elements).isEqualTo(new int[]{2, 4, 6}); 183 | } 184 | 185 | @Test 186 | public void filterNonUnique_return_unique_elements() throws Exception { 187 | int[] elements = Snippets.filterNonUnique(new int[]{1, 2, 2, 3, 4, 4, 5}); 188 | assertThat(elements).isEqualTo(new int[]{1, 3, 5}); 189 | } 190 | 191 | @Test 192 | public void filterNonUnique_return_same_array_when_all_unique() throws Exception { 193 | int[] elements = Snippets.filterNonUnique(new int[]{1, 2, 3, 4, 5}); 194 | assertThat(elements).isEqualTo(new int[]{1, 2, 3, 4, 5}); 195 | } 196 | 197 | @Test 198 | public void filterNonUnique_return_empty_array_when_all_duplicated() throws Exception { 199 | int[] elements = Snippets.filterNonUnique(new int[]{1, 1, 2, 2, 3, 3, 4, 4, 5, 5}); 200 | assertThat(elements).isEmpty(); 201 | } 202 | 203 | @Test 204 | public void flatten_flat_one_level_array() throws Exception { 205 | int[] flatten = Snippets.flatten(new Object[]{1, new int[]{2}, 3, 4}); 206 | assertThat(flatten).isEqualTo(new int[]{1, 2, 3, 4}); 207 | } 208 | 209 | @Test 210 | public void flattenDepth_flatten_to_specified_depth() throws Exception { 211 | Object[] input = { 212 | 1, 213 | new Object[]{2}, 214 | new Object[]{ 215 | new Object[]{ 216 | new Object[]{ 217 | 3 218 | }, 219 | 4 220 | }, 5 221 | } 222 | }; 223 | 224 | Object[] flatten = Snippets.flattenDepth(input, 2); 225 | assertThat(flatten).isEqualTo(new Object[]{1, 2, new Object[]{3}, 4, 5}); 226 | } 227 | 228 | @Test 229 | public void group_elements_by_length() throws Exception { 230 | Map> groups = Snippets.groupBy(new String[]{"one", "two", "three"}, String::length); 231 | assertThat(groups) 232 | .containsOnly( 233 | new SimpleEntry<>(3, Arrays.asList("one", "two")), 234 | new SimpleEntry<>(5, Collections.singletonList("three")) 235 | ); 236 | } 237 | 238 | @Test 239 | public void initial_return_array_except_last_element() throws Exception { 240 | Integer[] initial = Snippets.initial(new Integer[]{1, 2, 3}); 241 | assertThat(initial).isEqualTo(new Integer[]{1, 2}); 242 | } 243 | 244 | @Test 245 | public void initializeArrayWithRange_from_1_to_5() throws Exception { 246 | int[] numbers = Snippets.initializeArrayWithRange(5, 1); 247 | assertThat(numbers).isEqualTo(new int[]{1, 2, 3, 4, 5}); 248 | } 249 | 250 | @Test 251 | public void initializeArrayWithValues() throws Exception { 252 | int[] elements = Snippets.initializeArrayWithValues(5, 2); 253 | assertThat(elements).isEqualTo(new int[]{2, 2, 2, 2, 2}); 254 | } 255 | 256 | @Test 257 | public void intersection_between_two_arrays() throws Exception { 258 | int[] elements = Snippets.intersection(new int[]{1, 2, 3}, new int[]{4, 3, 2}); 259 | assertThat(elements).isEqualTo(new int[]{2, 3}); 260 | } 261 | 262 | @Test 263 | public void isSorted_return_1_when_array_sorted_is_ascending_order() throws Exception { 264 | int sorted = Snippets.isSorted(new Integer[]{0, 1, 2, 3}); 265 | assertThat(sorted).isEqualTo(1); 266 | 267 | sorted = Snippets.isSorted(new Integer[]{0, 1, 2, 2}); 268 | assertThat(sorted).isEqualTo(1); 269 | } 270 | 271 | @Test 272 | public void isSorted_return_minus_1_when_array_sorted_in_descending_order() throws Exception { 273 | int sorted = Snippets.isSorted(new Integer[]{3, 2, 1, 0}); 274 | assertThat(sorted).isEqualTo(-1); 275 | 276 | sorted = Snippets.isSorted(new Integer[]{3, 3, 2, 1, 0}); 277 | assertThat(sorted).isEqualTo(-1); 278 | } 279 | 280 | @Test 281 | public void isSorted_returns_0_when_array_is_not_sorted() throws Exception { 282 | int sorted = Snippets.isSorted(new Integer[]{3, 4, 1, 0}); 283 | assertThat(sorted).isEqualTo(0); 284 | } 285 | 286 | @Test 287 | public void join_should_create_string_from_an_array_with_different_sep_and_end() throws Exception { 288 | String joined = Snippets.join(new String[]{"pen", "pineapple", "apple", "pen"}, ",", "&"); 289 | assertThat(joined).isEqualTo("pen,pineapple,apple&pen"); 290 | } 291 | 292 | @Test 293 | public void join_should_create_string_from_an_array_with_sep_only() throws Exception { 294 | String joined = Snippets.join(new String[]{"pen", "pineapple", "apple", "pen"}, ","); 295 | assertThat(joined).isEqualTo("pen,pineapple,apple,pen"); 296 | } 297 | 298 | @Test 299 | public void join_should_create_string_from_an_array_with_default_sep() throws Exception { 300 | String joined = Snippets.join(new String[]{"pen", "pineapple", "apple", "pen"}); 301 | assertThat(joined).isEqualTo("pen,pineapple,apple,pen"); 302 | } 303 | 304 | @Test 305 | public void join_should_create_empty_string_with_empty_array() throws Exception { 306 | String joined = Snippets.join(new String[]{}); 307 | assertThat(joined).isEqualTo(""); 308 | } 309 | 310 | @Test 311 | public void nthElement_return_nth_element_from_start_when_n_is_greater_than_0() throws Exception { 312 | String nthElement = Snippets.nthElement(new String[]{"a", "b", "c"}, 1); 313 | assertThat(nthElement).isEqualTo("b"); 314 | } 315 | 316 | 317 | @Test 318 | public void nthElement_return_nth_element_from_end_when_n_is_less_than_0() throws Exception { 319 | String nthElement = Snippets.nthElement(new String[]{"a", "b", "c"}, -3); 320 | assertThat(nthElement).isEqualTo("a"); 321 | } 322 | 323 | @Test 324 | public void pick_should_pick_key_pairs_corresponding_to_keys() throws Exception { 325 | Map obj = new HashMap<>(); 326 | obj.put("a", 1); 327 | obj.put("b", 2); 328 | obj.put("c", 3); 329 | 330 | Map picked = Snippets.pick(obj, new String[]{"a", "c"}); 331 | assertThat(picked).containsOnly(new SimpleEntry<>("a", 1), new SimpleEntry<>("c", 3)); 332 | } 333 | 334 | @Test 335 | public void reducedFilter_Test() throws Exception { 336 | Map item1 = new HashMap<>(); 337 | item1.put("id", 1); 338 | item1.put("name", "john"); 339 | item1.put("age", 24); 340 | 341 | Map item2 = new HashMap<>(); 342 | item2.put("id", 2); 343 | item2.put("name", "mike"); 344 | item2.put("age", 50); 345 | 346 | Map[] filtered = Snippets.reducedFilter((Map[]) new Map[]{item1, item2}, new String[]{"id", "name"}, item -> (Integer) item.get("age") > 24); 347 | assertThat(filtered).hasSize(1); 348 | assertThat(filtered[0]) 349 | .containsOnly( 350 | new SimpleEntry("id", 2), 351 | new SimpleEntry("name", "mike")); 352 | } 353 | 354 | @Test 355 | public void sample_should_return_random_element() throws Exception { 356 | Integer sample = Snippets.sample(new Integer[]{3, 7, 9, 11}); 357 | assertThat(sample).isIn(Arrays.asList(3, 7, 9, 11)); 358 | } 359 | 360 | @Test 361 | public void sampleSize_should_return_sample_of_size_array_length_when_sample_size_is_greater_than_array_size() throws Exception { 362 | Integer[] sample = Snippets.sampleSize(new Integer[]{1, 2, 3}, 4); 363 | assertThat(sample).hasSize(3); 364 | } 365 | 366 | @Test 367 | public void similarity_test() throws Exception { 368 | Integer[] arr = Snippets.similarity(new Integer[]{1, 2, 3}, new Integer[]{1, 2, 4}); 369 | assertThat(arr).isEqualTo(new Integer[]{1, 2}); 370 | } 371 | 372 | @Test 373 | public void empty_array() throws Exception { 374 | String[] empty = Snippets.emptyArray(String.class); 375 | assertThat(empty).isEmpty(); 376 | } 377 | 378 | @Test 379 | public void sortedIndex_descending() throws Exception { 380 | int index = Snippets.sortedIndex(new Integer[]{5, 3, 2, 1}, 4); 381 | assertThat(index).isEqualTo(1); 382 | } 383 | 384 | @Test 385 | public void sortedIndex_ascending() throws Exception { 386 | int index = Snippets.sortedIndex(new Integer[]{30, 50}, 40); 387 | assertThat(index).isEqualTo(1); 388 | } 389 | 390 | @Test 391 | public void sortedIndex_ascending_at_end() throws Exception { 392 | int index = Snippets.sortedIndex(new Integer[]{30, 50}, 60); 393 | assertThat(index).isEqualTo(2); 394 | } 395 | 396 | @Test 397 | public void symmetricDifference_test() throws Exception { 398 | Integer[] diff = Snippets.symmetricDifference( 399 | new Integer[]{1, 2, 3}, 400 | new Integer[]{1, 2, 4} 401 | ); 402 | assertThat(diff).isEqualTo(new Integer[]{3, 4}); 403 | } 404 | 405 | @Test 406 | public void union_test() throws Exception { 407 | Integer[] union = Snippets.union( 408 | new Integer[]{1, 2, 3}, 409 | new Integer[]{1, 2, 4} 410 | ); 411 | 412 | assertThat(union).isEqualTo(new Integer[]{1, 2, 3, 4}); 413 | } 414 | 415 | @Test 416 | public void without_test() throws Exception { 417 | Integer[] without = Snippets.without( 418 | new Integer[]{2, 1, 2, 3}, 419 | 1, 2 420 | 421 | ); 422 | 423 | assertThat(without).isEqualTo(new Integer[]{3}); 424 | } 425 | 426 | @Test 427 | public void zip_test() throws Exception { 428 | List zipped = Snippets.zip( 429 | new String[]{"a", "b"}, 430 | new Integer[]{1, 2}, 431 | new Boolean[]{true, false} 432 | ); 433 | 434 | assertThat(zipped).hasSize(2); 435 | assertThat(zipped.get(0)).isEqualTo(new Object[]{"a", 1, true}); 436 | assertThat(zipped.get(1)).isEqualTo(new Object[]{"b", 2, false}); 437 | } 438 | 439 | @Test 440 | public void zip_test_2() throws Exception { 441 | List zipped = Snippets.zip( 442 | new String[]{"a"}, 443 | new Integer[]{1, 2}, 444 | new Boolean[]{true, false} 445 | ); 446 | 447 | assertThat(zipped).hasSize(2); 448 | assertThat(zipped.get(0)).isEqualTo(new Object[]{"a", 1, true}); 449 | assertThat(zipped.get(1)).isEqualTo(new Object[]{null, 2, false}); 450 | } 451 | 452 | @Test 453 | public void zipObject_test_1() throws Exception { 454 | Map map = Snippets.zipObject( 455 | new String[]{"a", "b", "c"}, 456 | new Integer[]{1, 2} 457 | ); 458 | 459 | assertThat(map).containsOnly( 460 | new SimpleEntry<>("a", 1), 461 | new SimpleEntry<>("b", 2), 462 | new SimpleEntry<>("c", null) 463 | ); 464 | } 465 | 466 | @Test 467 | public void zipObject_test_2() throws Exception { 468 | Map map = Snippets.zipObject( 469 | new String[]{"a", "b"}, 470 | new Integer[]{1, 2, 3} 471 | ); 472 | 473 | assertThat(map).containsOnly( 474 | new SimpleEntry<>("a", 1), 475 | new SimpleEntry<>("b", 2) 476 | ); 477 | } 478 | 479 | @Test 480 | public void average_of_1_to_10_is_5_dot_5() throws Exception { 481 | double average = Snippets.average(IntStream.rangeClosed(1, 10).toArray()); 482 | assertThat(average).isEqualTo(5.5); 483 | } 484 | 485 | @Test 486 | public void capitalize_test() throws Exception { 487 | assertThat(Snippets.capitalize("fooBar", false)).isEqualTo("FooBar"); 488 | assertThat(Snippets.capitalize("fooBar", true)).isEqualTo("Foobar"); 489 | } 490 | 491 | @Test 492 | public void capitalizeEveryWord_test() throws Exception { 493 | assertThat(Snippets.capitalizeEveryWord("hello world!")).isEqualTo("Hello World!"); 494 | } 495 | 496 | @Test 497 | public void anagrams_test() throws Exception { 498 | List anagrams = Snippets.anagrams("abc"); 499 | assertThat(anagrams) 500 | .containsOnly("abc", "acb", "bac", "bca", "cab", "cba"); 501 | } 502 | 503 | @Test 504 | public void byteSize_of_smiley_is_4() throws Exception { 505 | int length = Snippets.byteSize("\uD83D\uDE00"); 506 | assertThat(length).isEqualTo(4); 507 | } 508 | 509 | @Test 510 | public void byteSize_of_hello_world_is_11() throws Exception { 511 | assertThat(Snippets.byteSize("Hello World")).isEqualTo(11); 512 | } 513 | 514 | @Test 515 | public void countVowels_test() throws Exception { 516 | assertThat(Snippets.countVowels("foobar")).isEqualTo(3); 517 | } 518 | 519 | @Test 520 | public void escapeRegex_test() throws Exception { 521 | assertThat(Snippets.escapeRegExp("(test)")).isEqualTo("\\Q(test)\\E"); 522 | } 523 | 524 | @Test 525 | public void fromCamelCase_test() throws Exception { 526 | assertThat(Snippets.fromCamelCase("someJavaProperty", "_")) 527 | .isEqualTo("some_java_property"); 528 | assertThat(Snippets.fromCamelCase("someDatabaseFieldName", " ")) 529 | .isEqualTo("some database field name"); 530 | assertThat(Snippets.fromCamelCase("someLabelThatNeedsToBeCamelized", "-")) 531 | .isEqualTo("some-label-that-needs-to-be-camelized"); 532 | } 533 | 534 | @Test 535 | public void isAbsoluteUrl_test() throws Exception { 536 | assertThat(Snippets.isAbsoluteUrl("https://google.com")).isTrue(); 537 | assertThat(Snippets.isAbsoluteUrl("ftp://www.myserver.net")).isTrue(); 538 | assertThat(Snippets.isAbsoluteUrl("/foo/bar")).isFalse(); 539 | } 540 | 541 | @Test 542 | public void isLowerCase_test() throws Exception { 543 | assertThat(Snippets.isLowerCase("abc")).isTrue(); 544 | assertThat(Snippets.isLowerCase("a3@$")).isTrue(); 545 | assertThat(Snippets.isLowerCase("Ab4")).isFalse(); 546 | } 547 | 548 | @Test 549 | public void mask_test() throws Exception { 550 | assertThat(Snippets.mask("1234567890", 4, "*")).isEqualTo("******7890"); 551 | assertThat(Snippets.mask("1234567890", 3, "*")).isEqualTo("*******890"); 552 | assertThat(Snippets.mask("1234567890", -4, "*")).isEqualTo("1234******"); 553 | } 554 | 555 | @Test 556 | public void palindrome_test() throws Exception { 557 | assertThat(Snippets.isPalindrome("taco cat")).isTrue(); 558 | assertThat(Snippets.isPalindrome("abc")).isFalse(); 559 | } 560 | 561 | @Test 562 | public void reverseString_test() throws Exception { 563 | assertThat(Snippets.reverseString("foobar")).isEqualTo("raboof"); 564 | } 565 | 566 | @Test 567 | public void sortCharactersInString_test() throws Exception { 568 | assertThat(Snippets.sortCharactersInString("cabbage")).isEqualTo("aabbceg"); 569 | } 570 | 571 | @Test 572 | public void splitLines_test() throws Exception { 573 | assertThat(Snippets.splitLines("This\nis a\nmultiline\nstring.\n")) 574 | .isEqualTo(new String[]{ 575 | "This", 576 | "is a", 577 | "multiline", 578 | "string." 579 | }); 580 | } 581 | 582 | @Test 583 | public void toCamelCase_test() throws Exception { 584 | assertThat(Snippets.toCamelCase("some_database_field_name")).isEqualTo("someDatabaseFieldName"); 585 | assertThat(Snippets.toCamelCase("Some label that needs to be camelized")).isEqualTo("someLabelThatNeedsToBeCamelized"); 586 | assertThat(Snippets.toCamelCase("some-java-property")).isEqualTo("someJavaProperty"); 587 | assertThat(Snippets.toCamelCase("some-mixed_string with spaces_underscores-and-hyphens")).isEqualTo("someMixedStringWithSpacesUnderscoresAndHyphens"); 588 | } 589 | 590 | @Test 591 | public void toKebabCase_test() throws Exception { 592 | assertThat(Snippets.toKebabCase("camelCase")).isEqualTo("camel-case"); 593 | assertThat(Snippets.toKebabCase("some text")).isEqualTo("some-text"); 594 | assertThat(Snippets.toKebabCase("some-mixed_string With spaces_underscores-and-hyphens")).isEqualTo("some-mixed-string-with-spaces-underscores-and-hyphens"); 595 | assertThat(Snippets.toKebabCase("AllThe-small Things")).isEqualTo("all-the-small-things"); 596 | assertThat(Snippets.toKebabCase("IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingXMLAndHTML")).isEqualTo("i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-xml-and-html"); 597 | } 598 | 599 | @Test 600 | public void toSnakeCase_test() throws Exception { 601 | assertThat(Snippets.toSnakeCase("camelCase")).isEqualTo("camel_case"); 602 | assertThat(Snippets.toSnakeCase("some text")).isEqualTo("some_text"); 603 | assertThat(Snippets.toSnakeCase("some-mixed_string With spaces_underscores-and-hyphens")).isEqualTo("some_mixed_string_with_spaces_underscores_and_hyphens"); 604 | assertThat(Snippets.toSnakeCase("AllThe-small Things")).isEqualTo("all_the_small_things"); 605 | assertThat(Snippets.toSnakeCase("IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingXMLAndHTML")).isEqualTo("i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_xml_and_html"); 606 | } 607 | 608 | @Test 609 | public void truncateString_test() throws Exception { 610 | assertThat(Snippets.truncateString("boomerang", 7)).isEqualTo("boom..."); 611 | } 612 | 613 | @Test 614 | public void words_test() throws Exception { 615 | assertThat(Snippets.words("I love java!!")).isEqualTo(new String[]{"I", "love", "java"}); 616 | assertThat(Snippets.words("Kotlin, Java & LemonTea")).isEqualTo(new String[]{"Kotlin", "Java", "LemonTea"}); 617 | } 618 | 619 | @Test 620 | public void randomInts_test() throws Exception { 621 | assertThat(Snippets.randomInts(5, 100, 200)).hasSize(5); 622 | } 623 | 624 | @Test 625 | public void concat_test() throws Exception { 626 | String[] first = {"a", "b"}; 627 | String[] second = {"c", "d"}; 628 | assertThat(Snippets.concat(first, second)) 629 | .isEqualTo(new String[]{"a", "b", "c", "d"}); 630 | } 631 | 632 | @Test 633 | public void getCurrentWorkingDirectoryPath_test() throws Exception { 634 | assertThat(Snippets.getCurrentWorkingDirectoryPath()).isNotBlank(); 635 | } 636 | 637 | @Test 638 | public void isNumeric_test() throws Exception { 639 | assertThat(Snippets.isNumeric("123")).isTrue(); 640 | assertThat(Snippets.isNumeric("abc")).isFalse(); 641 | assertThat(Snippets.isNumeric("")).isFalse(); 642 | } 643 | 644 | @Test 645 | public void findNextPositivePowerOfTwo_test() throws Exception { 646 | assertThat(Snippets.findNextPositivePowerOfTwo(-1)).isEqualTo(1); 647 | assertThat(Snippets.findNextPositivePowerOfTwo(3)).isEqualTo(4); 648 | assertThat(Snippets.findNextPositivePowerOfTwo(31)).isEqualTo(32); 649 | assertThat(Snippets.findNextPositivePowerOfTwo(32)).isEqualTo(32); 650 | } 651 | 652 | @Test 653 | public void isEven_test() throws Exception { 654 | assertThat(Snippets.isEven(1)).isFalse(); 655 | assertThat(Snippets.isEven(2)).isTrue(); 656 | assertThat(Snippets.isEven(3)).isFalse(); 657 | assertThat(Snippets.isEven(4)).isTrue(); 658 | assertThat(Snippets.isEven(-1)).isFalse(); 659 | } 660 | 661 | @Test 662 | public void stringToIntegers_test() throws Exception { 663 | int[] intArray = Snippets.stringToIntegers("1 2 3 4 5"); 664 | assertThat(intArray).isEqualTo(new int[]{1, 2, 3, 4, 5}); 665 | } 666 | 667 | private static class Class1 implements I2, I1, I5 { 668 | // empty 669 | } 670 | 671 | private static class Class2 extends Class1 implements I2, I3 { 672 | // empty 673 | } 674 | 675 | private interface I1 { 676 | // empty 677 | } 678 | 679 | private interface I2 { 680 | // empty 681 | } 682 | 683 | private interface I3 extends I4, I5 { 684 | // empty 685 | } 686 | 687 | private interface I4 { 688 | // empty 689 | } 690 | 691 | private interface I5 extends I6 { 692 | // empty 693 | } 694 | 695 | private interface I6 { 696 | // empty 697 | } 698 | 699 | @Test 700 | public void getAllInterfaces_shouldFindAllInterfacesImplementedByAClass() { 701 | final List> list = Snippets.getAllInterfaces(Class2.class); 702 | assertThat(list).hasSize(6); 703 | assertThat(list).containsExactly(I2.class, I3.class, I4.class, I5.class, I6.class, I1.class); 704 | } 705 | 706 | enum Priority { 707 | High, Medium, Low 708 | } 709 | 710 | @Test 711 | public void getEnumMap_convert_enum_to_map() throws Exception { 712 | Map map = Snippets.getEnumMap(Priority.class); 713 | assertThat(map).hasSize(3); 714 | assertThat(map) 715 | .containsOnly( 716 | new SimpleEntry<>("High", Priority.High), 717 | new SimpleEntry<>("Medium", Priority.Medium), 718 | new SimpleEntry<>("Low", Priority.Low) 719 | ); 720 | } 721 | } -------------------------------------------------------------------------------- /src/main/java/snippets/Snippets.java: -------------------------------------------------------------------------------- 1 | package snippets; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.PrintWriter; 8 | import java.io.StringWriter; 9 | import java.lang.management.ManagementFactory; 10 | import java.lang.management.RuntimeMXBean; 11 | import java.lang.reflect.Array; 12 | import java.nio.charset.StandardCharsets; 13 | import java.nio.file.FileSystems; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | import java.util.AbstractMap.SimpleEntry; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.Collections; 20 | import java.util.HashMap; 21 | import java.util.HashSet; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.Objects; 25 | import java.util.OptionalInt; 26 | import java.util.Set; 27 | import java.util.concurrent.ThreadLocalRandom; 28 | import java.util.function.Function; 29 | import java.util.function.IntBinaryOperator; 30 | import java.util.function.IntFunction; 31 | import java.util.function.IntPredicate; 32 | import java.util.function.Predicate; 33 | import java.util.regex.Matcher; 34 | import java.util.regex.Pattern; 35 | import java.util.stream.Collectors; 36 | import java.util.stream.IntStream; 37 | import java.util.stream.Stream; 38 | 39 | public abstract class Snippets { 40 | 41 | /** 42 | * Calculates the greatest common denominator (gcd) of an array of numbers 43 | * 44 | * @param numbers Array of numbers 45 | * @return gcd of array of numbers 46 | */ 47 | public static OptionalInt gcd(int[] numbers) { 48 | return Arrays.stream(numbers) 49 | .reduce((a, b) -> gcd(a, b)); 50 | } 51 | 52 | /** 53 | * Calculates the lowest common multiple (lcm) of an array of numbers. 54 | * 55 | * @param numbers Array of numbers 56 | * @return lcm of array of numbers 57 | */ 58 | public static OptionalInt lcm(int[] numbers) { 59 | IntBinaryOperator lcm = (x, y) -> (x * y) / gcd(x, y); 60 | return Arrays.stream(numbers) 61 | .reduce((a, b) -> lcm.applyAsInt(a, b)); 62 | } 63 | 64 | private static int gcd(int a, int b) { 65 | if (b == 0) { 66 | return a; 67 | } 68 | return gcd(b, a % b); 69 | } 70 | 71 | /** 72 | * Returns the maximum value in an array. 73 | * 74 | * @param numbers Array of numbers 75 | * @return maximum value in an array 76 | */ 77 | public static OptionalInt arrayMax(int[] numbers) { 78 | return Arrays.stream(numbers).max(); 79 | } 80 | 81 | /** 82 | * Returns the minimum value in an array. 83 | * 84 | * @param numbers Array of numbers 85 | * @return minimum value in an array 86 | */ 87 | public static OptionalInt arrayMin(int[] numbers) { 88 | return Arrays.stream(numbers).min(); 89 | } 90 | 91 | /** 92 | * Chunks an array into smaller arrays of a specified size. 93 | * 94 | * @param numbers Input array of numbers 95 | * @param size The chunk size 96 | * @return Smaller chunks 97 | */ 98 | public static int[][] chunk(int[] numbers, int size) { 99 | return IntStream.iterate(0, i -> i + size) 100 | .limit((long) Math.ceil((double) numbers.length / size)) 101 | .mapToObj(cur -> Arrays.copyOfRange(numbers, cur, cur + size > numbers.length ? numbers.length : cur + size)) 102 | .toArray(int[][]::new); 103 | } 104 | 105 | /** 106 | * Counts the occurrences of a value in an array. 107 | * 108 | * @param numbers Array of numbers 109 | * @param value the value for which we have to count occurrences 110 | * @return count of total number of occurrences of the value 111 | */ 112 | public static long countOccurrences(int[] numbers, int value) { 113 | return Arrays.stream(numbers) 114 | .filter(number -> number == value) 115 | .count(); 116 | } 117 | 118 | /** 119 | * Deep flattens an array. 120 | * 121 | * @param input A nested array containing integers 122 | * @return flattened array 123 | */ 124 | public static int[] deepFlatten(Object[] input) { 125 | return Arrays.stream(input) 126 | .flatMapToInt(o -> { 127 | if (o instanceof Object[]) { 128 | return Arrays.stream(deepFlatten((Object[]) o)); 129 | } 130 | return IntStream.of((Integer) o); 131 | }).toArray(); 132 | } 133 | 134 | /** 135 | * Returns the difference between two arrays. 136 | * 137 | * @param first the first array 138 | * @param second the second array 139 | * @return Elements in first that are not in second 140 | */ 141 | public static int[] difference(int[] first, int[] second) { 142 | Set set = Arrays.stream(second).boxed().collect(Collectors.toSet()); 143 | return Arrays.stream(first) 144 | .filter(v -> !set.contains(v)) 145 | .toArray(); 146 | } 147 | 148 | /** 149 | * Filters out all values from an array for which the comparator function does not return true. 150 | * 151 | * @param first the first array 152 | * @param second the second array 153 | * @param comparator the comparator function 154 | * @return the resulting array 155 | */ 156 | public static int[] differenceWith(int[] first, int[] second, IntBinaryOperator comparator) { 157 | return Arrays.stream(first) 158 | .filter(a -> 159 | Arrays.stream(second) 160 | .noneMatch(b -> comparator.applyAsInt(a, b) == 0) 161 | ).toArray(); 162 | } 163 | 164 | /** 165 | * Returns all the distinct values of an array. 166 | * 167 | * @param elements ints 168 | * @return distinct values 169 | */ 170 | public static int[] distinctValuesOfArray(int[] elements) { 171 | return Arrays.stream(elements).distinct().toArray(); 172 | } 173 | 174 | /** 175 | * Removes elements in an array until the passed function returns true. Returns the remaining elements in the array. 176 | * 177 | * @param elements 178 | * @param condition 179 | * @return 180 | */ 181 | public static int[] dropElements(int[] elements, IntPredicate condition) { 182 | while (elements.length > 0 && !condition.test(elements[0])) { 183 | elements = Arrays.copyOfRange(elements, 1, elements.length); 184 | } 185 | return elements; 186 | } 187 | 188 | /** 189 | * Returns a new array with n elements removed from the right 190 | * 191 | * @param elements 192 | * @param n number of elements to remove 193 | * @return array after removing n elements 194 | */ 195 | public static int[] dropRight(int[] elements, int n) { 196 | if (n < 0) { 197 | throw new IllegalArgumentException("n is less than 0"); 198 | } 199 | return n < elements.length 200 | ? Arrays.copyOfRange(elements, 0, elements.length - n) 201 | : new int[0]; 202 | } 203 | 204 | /** 205 | * Returns every nth element in an array. 206 | * 207 | * @param elements 208 | * @param nth 209 | * @return 210 | */ 211 | public static int[] everyNth(int[] elements, int nth) { 212 | return IntStream.range(0, elements.length) 213 | .filter(i -> i % nth == nth - 1) 214 | .map(i -> elements[i]) 215 | .toArray(); 216 | } 217 | 218 | /** 219 | * Filters out the non-unique values in an array. 220 | *

221 | * Use Array.stream().filter() for an array containing only the unique values. 222 | * 223 | * @param elements input array 224 | * @return unique values in the array 225 | */ 226 | public static int[] filterNonUnique(int[] elements) { 227 | return Arrays.stream(elements) 228 | .filter(el -> indexOf(elements, el) == lastIndexOf(elements, el)) 229 | .toArray(); 230 | } 231 | 232 | /** 233 | * Find index of element in the array. Return -1 in case element does not exist. 234 | *

235 | * Uses IntStream.range().filter() to find index of the element in the array. 236 | * 237 | * @param elements input array 238 | * @param el element to find 239 | * @return index of the element 240 | */ 241 | public static int indexOf(int[] elements, int el) { 242 | return IntStream.range(0, elements.length) 243 | .filter(idx -> elements[idx] == el) 244 | .findFirst() 245 | .orElse(-1); 246 | } 247 | 248 | /** 249 | * Find last index of element in the array. Return -1 in case element does not exist. 250 | *

251 | * Uses IntStream.iterate().limit().filter() to find index of the element in the array. 252 | * 253 | * @param elements input array 254 | * @param el element to find 255 | * @return index of the element 256 | */ 257 | public static int lastIndexOf(int[] elements, int el) { 258 | return IntStream.iterate(elements.length - 1, i -> i - 1) 259 | .limit(elements.length) 260 | .filter(idx -> elements[idx] == el) 261 | .findFirst() 262 | .orElse(-1); 263 | } 264 | 265 | /** 266 | * Flattens an array. 267 | * 268 | * @param elements input array 269 | * @return flattened array 270 | */ 271 | public static int[] flatten(Object[] elements) { 272 | return Arrays.stream(elements) 273 | .flatMapToInt(el -> el instanceof int[] 274 | ? Arrays.stream((int[]) el) 275 | : IntStream.of((int) el) 276 | ).toArray(); 277 | } 278 | 279 | /** 280 | * Flattens an array up to the specified depth. 281 | * 282 | * @param elements input array 283 | * @param depth depth to which to flatten array 284 | * @return flattened array 285 | */ 286 | public static Object[] flattenDepth(Object[] elements, int depth) { 287 | if (depth == 0) { 288 | return elements; 289 | } 290 | return Arrays.stream(elements) 291 | .flatMap(el -> el instanceof Object[] 292 | ? Arrays.stream(flattenDepth((Object[]) el, depth - 1)) 293 | : Arrays.stream(new Object[]{el}) 294 | ).toArray(); 295 | 296 | 297 | } 298 | 299 | /** 300 | * Groups the elements of an array based on the given function. 301 | * 302 | * @param elements input array 303 | * @param func function 304 | * @param type parameter 305 | * @return grouped elements in a Map 306 | */ 307 | public static Map> groupBy(T[] elements, Function func) { 308 | return Arrays.stream(elements).collect(Collectors.groupingBy(func)); 309 | } 310 | 311 | /** 312 | * Returns all the elements of an array except the last one. 313 | * Use Arrays.copyOfRange() to return all except the last one 314 | * 315 | * @param elements 316 | * @param 317 | * @return 318 | */ 319 | public static T[] initial(T[] elements) { 320 | return Arrays.copyOfRange(elements, 0, elements.length - 1); 321 | } 322 | 323 | /** 324 | * Initializes an array containing the numbers in the specified range where start and end are inclusive. 325 | * 326 | * @param end 327 | * @param start 328 | * @return 329 | */ 330 | public static int[] initializeArrayWithRange(int end, int start) { 331 | return IntStream.rangeClosed(start, end).toArray(); 332 | } 333 | 334 | public static int[] initializeArrayWithValues(int n, int value) { 335 | return IntStream.generate(() -> value).limit(n).toArray(); 336 | } 337 | 338 | public static int[] intersection(int[] first, int[] second) { 339 | Set set = Arrays.stream(second).boxed().collect(Collectors.toSet()); 340 | return Arrays.stream(first) 341 | .filter(set::contains) 342 | .toArray(); 343 | } 344 | 345 | public static > int isSorted(T[] arr) { 346 | final int direction = arr[0].compareTo(arr[1]) < 0 ? 1 : -1; 347 | for (int i = 0; i < arr.length; i++) { 348 | T val = arr[i]; 349 | if (i == arr.length - 1) return direction; 350 | else if ((val.compareTo(arr[i + 1]) * direction > 0)) return 0; 351 | } 352 | return direction; 353 | } 354 | 355 | public static String join(T[] arr, String separator, String end) { 356 | return IntStream.range(0, arr.length) 357 | .mapToObj(i -> new SimpleEntry<>(i, arr[i])) 358 | .reduce("", (acc, val) -> val.getKey() == arr.length - 2 359 | ? acc + val.getValue() + end 360 | : val.getKey() == arr.length - 1 ? acc + val.getValue() : acc + val.getValue() + separator, (fst, snd) -> fst); 361 | } 362 | 363 | public static String join(T[] arr, String separator) { 364 | return join(arr, separator, separator); 365 | } 366 | 367 | public static String join(T[] arr) { 368 | return join(arr, ","); 369 | } 370 | 371 | public static T nthElement(T[] arr, int n) { 372 | if (n > 0) { 373 | return Arrays.copyOfRange(arr, n, arr.length)[0]; 374 | } 375 | return Arrays.copyOfRange(arr, arr.length + n, arr.length)[0]; 376 | } 377 | 378 | public static Map pick(Map obj, T[] arr) { 379 | return Arrays.stream(arr) 380 | .filter(obj::containsKey) 381 | .collect(Collectors.toMap(k -> k, obj::get)); 382 | } 383 | 384 | public static Map[] reducedFilter(Map[] data, String[] keys, Predicate> fn) { 385 | return Arrays.stream(data) 386 | .filter(fn) 387 | .map(el -> Arrays.stream(keys).filter(el::containsKey) 388 | .collect(Collectors.toMap(Function.identity(), el::get))) 389 | .toArray((IntFunction[]>) Map[]::new); 390 | } 391 | 392 | public static T sample(T[] arr) { 393 | return arr[(int) Math.floor(Math.random() * arr.length)]; 394 | } 395 | 396 | public static T[] sampleSize(T[] input, int n) { 397 | T[] arr = Arrays.copyOf(input, input.length); 398 | int length = arr.length; 399 | int m = length; 400 | while (m > 0) { 401 | int i = (int) Math.floor(Math.random() * m--); 402 | T tmp = arr[i]; 403 | arr[i] = arr[m]; 404 | arr[m] = tmp; 405 | } 406 | return Arrays.copyOfRange(arr, 0, n > length ? length : n); 407 | } 408 | 409 | public static T[] shuffle(T[] input) { 410 | T[] arr = Arrays.copyOf(input, input.length); 411 | int length = arr.length; 412 | int m = length; 413 | while (m > 0) { 414 | int i = (int) Math.floor(Math.random() * m--); 415 | T tmp = arr[i]; 416 | arr[i] = arr[m]; 417 | arr[m] = tmp; 418 | } 419 | return arr; 420 | } 421 | 422 | public static T[] similarity(T[] first, T[] second) { 423 | return Arrays.stream(first) 424 | .filter(a -> Arrays.stream(second).anyMatch(b -> Objects.equals(a, b))) 425 | // Make a new array of first's runtime type, but empty content: 426 | .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 427 | } 428 | 429 | public static T[] emptyArray(Class clz) { 430 | return (T[]) Array.newInstance(clz, 0); 431 | } 432 | 433 | 434 | public static > int sortedIndex(T[] arr, T el) { 435 | boolean isDescending = arr[0].compareTo(arr[arr.length - 1]) > 0; 436 | return IntStream.range(0, arr.length) 437 | .filter(i -> isDescending ? el.compareTo(arr[i]) >= 0 : el.compareTo(arr[i]) <= 0) 438 | .findFirst() 439 | .orElse(arr.length); 440 | } 441 | 442 | public static T[] symmetricDifference(T[] first, T[] second) { 443 | Set sA = new HashSet<>(Arrays.asList(first)); 444 | Set sB = new HashSet<>(Arrays.asList(second)); 445 | 446 | return Stream.concat( 447 | Arrays.stream(first).filter(a -> !sB.contains(a)), 448 | Arrays.stream(second).filter(b -> !sA.contains(b)) 449 | ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 450 | } 451 | 452 | public static T[] tail(T[] arr) { 453 | return arr.length > 1 454 | ? Arrays.copyOfRange(arr, 1, arr.length) 455 | : arr; 456 | } 457 | 458 | public static T[] take(T[] arr, int n) { 459 | return Arrays.copyOfRange(arr, 0, n); 460 | } 461 | 462 | public static T[] takeRight(T[] arr, int n) { 463 | return Arrays.copyOfRange(arr, arr.length - n, arr.length); 464 | } 465 | 466 | public static T[] union(T[] first, T[] second) { 467 | Set set = new HashSet<>(Arrays.asList(first)); 468 | set.addAll(Arrays.asList(second)); 469 | return set.toArray((T[]) Arrays.copyOf(new Object[0], 0, first.getClass())); 470 | } 471 | 472 | public static T[] without(T[] arr, T... elements) { 473 | List excludeElements = Arrays.asList(elements); 474 | return Arrays.stream(arr) 475 | .filter(el -> !excludeElements.contains(el)) 476 | .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, arr.getClass())); 477 | } 478 | 479 | public static List zip(Object[]... arrays) { 480 | OptionalInt max = Arrays.stream(arrays).mapToInt(arr -> arr.length).max(); 481 | return IntStream.range(0, max.getAsInt()) 482 | .mapToObj(i -> Arrays.stream(arrays) 483 | .map(arr -> i < arr.length ? arr[i] : null) 484 | .toArray()) 485 | .collect(Collectors.toList()); 486 | } 487 | 488 | public static Map zipObject(String[] props, Object[] values) { 489 | return IntStream.range(0, props.length) 490 | .mapToObj(i -> new SimpleEntry<>(props[i], i < values.length ? values[i] : null)) 491 | .collect( 492 | HashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), HashMap::putAll); 493 | } 494 | 495 | public static double average(int[] arr) { 496 | return IntStream.of(arr) 497 | .average() 498 | .orElseThrow(() -> new IllegalArgumentException("Array is empty")); 499 | } 500 | 501 | public static List anagrams(String input) { 502 | if (input.length() <= 2) { 503 | return input.length() == 2 504 | ? Arrays.asList(input, input.substring(1) + input.substring(0, 1)) 505 | : Collections.singletonList(input); 506 | } 507 | return IntStream.range(0, input.length()) 508 | .mapToObj(i -> new SimpleEntry<>(i, input.substring(i, i + 1))) 509 | .flatMap(entry -> 510 | anagrams(input.substring(0, entry.getKey()) + input.substring(entry.getKey() + 1)) 511 | .stream() 512 | .map(s -> entry.getValue() + s)) 513 | .collect(Collectors.toList()); 514 | } 515 | 516 | public static int byteSize(String input) { 517 | // Read the link below to learn more 518 | // https://stackoverflow.com/questions/16270994/difference-between-string-length-and-string-getbytes-length 519 | return input.getBytes().length; 520 | } 521 | 522 | public static String capitalize(String input, boolean lowerRest) { 523 | return input.substring(0, 1).toUpperCase() + 524 | (lowerRest 525 | ? input.substring(1, input.length()).toLowerCase() 526 | : input.substring(1, input.length())); 527 | } 528 | 529 | public static String capitalizeEveryWord(final String input) { 530 | return Pattern.compile("\\b(?=\\w)").splitAsStream(input) 531 | .map(w -> capitalize(w, false)) 532 | .collect(Collectors.joining()); 533 | } 534 | 535 | public static int countVowels(String input) { 536 | return input.replaceAll("[^aeiouAEIOU]", "").length(); 537 | } 538 | 539 | public static String escapeRegExp(String input) { 540 | return Pattern.quote(input); 541 | } 542 | 543 | public static String fromCamelCase(String input, String separator) { 544 | return input 545 | .replaceAll("([a-z\\d])([A-Z])", "$1" + separator + "$2") 546 | .toLowerCase(); 547 | } 548 | 549 | public static boolean isAbsoluteUrl(String url) { 550 | return Pattern.compile("^[a-z][a-z0-9+.-]*:").matcher(url).find(); 551 | } 552 | 553 | public static boolean isLowerCase(String input) { 554 | return Objects.equals(input, input.toLowerCase()); 555 | } 556 | 557 | public static boolean isUpperCase(String input) { 558 | return Objects.equals(input, input.toUpperCase()); 559 | } 560 | 561 | public static String mask(String input, int num, String mask) { 562 | int length = input.length(); 563 | return num > 0 564 | ? 565 | input.substring(0, length - num).replaceAll(".", mask) 566 | + input.substring(length - num) 567 | : 568 | input.substring(0, Math.negateExact(num)) 569 | + input.substring(Math.negateExact(num), length).replaceAll(".", mask); 570 | } 571 | 572 | public static boolean isPalindrome(String input) { 573 | String s = input.toLowerCase().replaceAll("[\\W_]", ""); 574 | return Objects.equals( 575 | s, 576 | new StringBuilder(s).reverse().toString() 577 | ); 578 | } 579 | 580 | public static String reverseString(String input) { 581 | return new StringBuilder(input).reverse().toString(); 582 | } 583 | 584 | public static String sortCharactersInString(String input) { 585 | return Arrays.stream(input.split("")).sorted().collect(Collectors.joining()); 586 | } 587 | 588 | public static String[] splitLines(String input) { 589 | return input.split("\\r?\\n"); 590 | } 591 | 592 | public static String toCamelCase(String input) { 593 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 594 | List matchedParts = new ArrayList<>(); 595 | while (matcher.find()) { 596 | matchedParts.add(matcher.group(0)); 597 | } 598 | String s = matchedParts.stream() 599 | .map(x -> x.substring(0, 1).toUpperCase() + x.substring(1).toLowerCase()) 600 | .collect(Collectors.joining()); 601 | return s.substring(0, 1).toLowerCase() + s.substring(1); 602 | } 603 | 604 | public static String toKebabCase(String input) { 605 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 606 | List matchedParts = new ArrayList<>(); 607 | while (matcher.find()) { 608 | matchedParts.add(matcher.group(0)); 609 | } 610 | return matchedParts.stream() 611 | .map(String::toLowerCase) 612 | .collect(Collectors.joining("-")); 613 | } 614 | 615 | public static List match(String input, String regex) { 616 | Matcher matcher = Pattern.compile(regex).matcher(input); 617 | List matchedParts = new ArrayList<>(); 618 | while (matcher.find()) { 619 | matchedParts.add(matcher.group(0)); 620 | } 621 | return matchedParts; 622 | } 623 | 624 | public static String toSnakeCase(String input) { 625 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 626 | List matchedParts = new ArrayList<>(); 627 | while (matcher.find()) { 628 | matchedParts.add(matcher.group(0)); 629 | } 630 | return matchedParts.stream() 631 | .map(String::toLowerCase) 632 | .collect(Collectors.joining("_")); 633 | } 634 | 635 | public static String truncateString(String input, int num) { 636 | return input.length() > num 637 | ? input.substring(0, num > 3 ? num - 3 : num) + "..." 638 | : input; 639 | } 640 | 641 | public static String[] words(String input) { 642 | return Arrays.stream(input.split("[^a-zA-Z-]+")) 643 | .filter(s -> !s.isEmpty()) 644 | .toArray(String[]::new); 645 | } 646 | 647 | //Read the link below for more information 648 | // https://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string 649 | public static String convertInputStreamToString(final InputStream in) throws IOException { 650 | ByteArrayOutputStream result = new ByteArrayOutputStream(); 651 | byte[] buffer = new byte[1024]; 652 | int length; 653 | while ((length = in.read(buffer)) != -1) { 654 | result.write(buffer, 0, length); 655 | } 656 | return result.toString(StandardCharsets.UTF_8.name()); 657 | } 658 | 659 | public static int[] randomInts(int total, int start, int end) { 660 | return ThreadLocalRandom.current().ints(total, start, end).toArray(); 661 | } 662 | 663 | public String readFileAsString(Path path) throws IOException { 664 | return new String(Files.readAllBytes(path)); 665 | } 666 | 667 | public static String stackTraceAsString(final Throwable throwable) { 668 | final StringWriter sw = new StringWriter(); 669 | throwable.printStackTrace(new PrintWriter(sw)); 670 | return sw.toString(); 671 | } 672 | 673 | public static T[] concat(T[] first, T[] second) { 674 | return Stream.concat( 675 | Stream.of(first), 676 | Stream.of(second) 677 | ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 678 | } 679 | 680 | public static String getCurrentWorkingDirectoryPath() { 681 | return FileSystems.getDefault().getPath("").toAbsolutePath().toString(); 682 | } 683 | 684 | public static boolean isNumeric(final String input) { 685 | if (input == null || input.isEmpty()) { 686 | return false; 687 | } 688 | return IntStream.range(0, input.length()) 689 | .allMatch(i -> Character.isDigit(input.charAt(i))); 690 | } 691 | 692 | public static int findNextPositivePowerOfTwo(int value) { 693 | return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); 694 | } 695 | 696 | public static boolean isEven(final int value) { 697 | return (value & 0b1) == 0; 698 | } 699 | 700 | public static boolean isPowerOfTwo(final int value) { 701 | return value > 0 && ((value & (~value + 1)) == value); 702 | } 703 | 704 | public static int generateRandomInt() { 705 | return ThreadLocalRandom.current().nextInt(); 706 | } 707 | 708 | public static String tmpDirName() { 709 | String tmpDirName = System.getProperty("java.io.tmpdir"); 710 | if (!tmpDirName.endsWith(File.separator)) { 711 | tmpDirName += File.separator; 712 | } 713 | 714 | return tmpDirName; 715 | } 716 | 717 | public static String osName() { 718 | return System.getProperty("os.name").toLowerCase(); 719 | } 720 | 721 | public static boolean isDebuggerAttached() { 722 | final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); 723 | return runtimeMXBean.getInputArguments() 724 | .stream() 725 | .anyMatch(arg -> arg.contains("-agentlib:jdwp")); 726 | 727 | } 728 | 729 | /** 730 | * Input a line of numbers separated by space as integers 731 | * and return ArrayList of Integers. 732 | * eg. the String "1 2 3 4 5 6 7 8 9" is returned as an ArrayList of Integers. 733 | * 734 | * @param numbers range of numbers separated by space as a string 735 | * @return ArrayList of Integers 736 | */ 737 | 738 | public static int[] stringToIntegers(String numbers) { 739 | return Arrays.stream(numbers.split(" ")).mapToInt(Integer::parseInt).toArray(); 740 | } 741 | 742 | /* Class Utilities */ 743 | 744 | public static List> getAllInterfaces(final Class cls) { 745 | return Stream.concat( 746 | Arrays.stream(cls.getInterfaces()).flatMap(intf -> 747 | Stream.concat(Stream.of(intf), getAllInterfaces(intf).stream())), 748 | cls.getSuperclass() == null ? Stream.empty() : getAllInterfaces(cls.getSuperclass()).stream() 749 | ).distinct().collect(Collectors.toList()); 750 | } 751 | 752 | public static boolean isInnerClass(final Class cls) { 753 | return cls != null && cls.getEnclosingClass() != null; 754 | } 755 | 756 | public static > Map getEnumMap(final Class enumClass) { 757 | return Arrays.stream(enumClass.getEnumConstants()) 758 | .collect(Collectors.toMap(Enum::name, Function.identity())); 759 | } 760 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 30 seconds of java8 2 | 3 | [![License](https://img.shields.io/badge/license-CC0--1.0-blue.svg)](https://github.com/biezhi/30-seconds-of-java8/blob/master/LICENSE) 4 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) 5 | [![Travis Build](https://travis-ci.org/biezhi/30-seconds-of-java8.svg?branch=master)](https://travis-ci.org/biezhi/30-seconds-of-java8) 6 | [![@biezhi on zhihu](https://img.shields.io/badge/zhihu-%40biezhi-red.svg)](https://www.zhihu.com/people/biezhi) 7 | [![](https://img.shields.io/github/followers/biezhi.svg?style=social&label=Follow%20Me)](https://github.com/biezhi) 8 | 9 | > 你可以在30秒或更短时间内收集有用的Java8代码片段。 10 | 11 | - 使用 Ctrl + F 或者 command + F 来查找代码片段。 12 | - 代码片段基于 Java8,如果你还不熟悉可以在[这里](https://zhuanlan.zhihu.com/java8)学习。 13 | - 代码片段翻译自 [little-java-functions](https://github.com/shekhargulati/little-java-functions) 14 | 15 | ## 目录 16 | 17 | ### 📚 Array (数组相关) 18 | 19 |

20 | 详细信息 21 | 22 | * [`chunk`](#chunk) 23 | * [`countOccurrences`](#countoccurrences) 24 | * [`deepFlatten`](#deepflatten) 25 | * [`difference`](#difference) 26 | * [`differenceWith`](#differencewith) 27 | * [`distinctValuesOfArray`](#distinctvaluesofarray) 28 | * [`dropElements`](#dropelements) 29 | * [`dropRight`](#dropright) 30 | * [`everyNth`](#everynth) 31 | * [`filterNonUnique`](#filternonunique) 32 | * [`flatten`](#flatten) 33 | * [`flattenDepth`](#flattendepth) 34 | * [`groupBy`](#groupby) 35 | * [`head`](#head) 36 | * [`initial`](#initial) 37 | * [`initializeArrayWithRange`](#initializearraywithrange) 38 | * [`initializeArrayWithValues`](#initializearraywithvalues) 39 | * [`intersection`](#intersection) 40 | * [`isSorted`](#issorted) 41 | * [`join`](#join) 42 | * [`nthElement`](#nthelement) 43 | * [`pick`](#pick) 44 | * [`reducedFilter`](#reducedfilter) 45 | * [`remove`](#remove) 46 | * [`sample`](#sample) 47 | * [`sampleSize`](#samplesize) 48 | * [`shuffle`](#shuffle) 49 | * [`similarity`](#similarity) 50 | * [`sortedIndex`](#sortedindex) 51 | * [`symmetricDifference`](#symmetricdifference) 52 | * [`tail`](#tail) 53 | * [`take`](#take) 54 | * [`takeRight`](#takeright) 55 | * [`union`](#union) 56 | * [`without`](#without) 57 | * [`zip`](#zip) 58 | * [`zipObject`](#zipobject) 59 | 60 |
61 | 62 | ### ➗ Math (数学相关) 63 | 64 |
65 | 详细信息 66 | 67 | * [`average`](#average) 68 | * [`gcd`](#gcd) 69 | * [`lcm`](#lcm) 70 | * [`findNextPositivePowerOfTwo`](#findnextpositivepoweroftwo) 71 | * [`isEven`](#iseven) 72 | * [`isPowerOfTwo`](#ispoweroftwo) 73 | * [`generateRandomInt`](#generaterandomint) 74 | 75 |
76 | 77 | ### 📜 String (字符串相关) 78 | 79 |
80 | 详细信息 81 | 82 | * [`anagrams`](#anagrams) 83 | * [`byteSize`](#bytesize) 84 | * [`capitalize`](#capitalize) 85 | * [`capitalizeEveryWord`](#capitalizeeveryword) 86 | * [`countVowels`](#countvowels) 87 | * [`escapeRegExp`](#escaperegexp) 88 | * [`fromCamelCase`](#fromcamelcase) 89 | * [`isAbsoluteURL`](#isabsoluteurl) 90 | * [`isLowerCase`](#islowercase) 91 | * [`isUpperCase`](#isuppercase) 92 | * [`isPalindrome`](#ispalindrome) 93 | * [`isNumeric`](#isnumeric) 94 | * [`mask`](#mask) 95 | * [`reverseString`](#reversestring) 96 | * [`sortCharactersInString`](#sortcharactersinstring) 97 | * [`splitLines`](#splitlines) 98 | * [`toCamelCase`](#tocamelcase) 99 | * [`toKebabCase`](#tokebabcase) 100 | * [`match`](#match) 101 | * [`toSnakeCase`](#tosnakecase) 102 | * [`truncateString`](#truncatestring) 103 | * [`words`](#words) 104 | * [`stringToIntegers`](#stringtointegers) 105 | 106 |
107 | 108 | ### ⭕️ IO (IO流相关) 109 | 110 |
111 | 详细信息 112 | 113 | * [`convertInputStreamToString`](#convertinputstreamtostring) 114 | * [`readFileAsString`](#readfileasstring) 115 | * [`getCurrentWorkingDirectoryPath`](#getcurrentworkingdirectorypath) 116 | * [`tmpDirName`](#tmpdirname) 117 | 118 |
119 | 120 | ### ❌ Exception (异常相关) 121 | 122 |
123 | 详细信息 124 | 125 | * [`stackTraceAsString`](#stacktraceasstring) 126 | 127 |
128 | 129 | ### 🖥 System (系统相关) 130 | 131 |
132 | 详细信息 133 | 134 | - [`osName`](#osname) 135 | - [`isDebuggerEnabled`](#isdebuggerenabled) 136 | 137 |
138 | 139 | ### 💡 Class (类相关) 140 | 141 |
142 | 详细信息 143 | 144 | - [`getAllInterfaces`](#getallinterfaces) 145 | - [`IsInnerClass`](#isinnerclass) 146 | 147 |
148 | 149 | ### 💎 Enum (枚举相关) 150 | 151 |
152 | 详细信息 153 | 154 | - [`getEnumMap`](#getenummap) 155 | 156 |
157 | 158 | ## Array 159 | 160 | ### chunk 161 | 162 | 将数组分割成特定大小的小数组。 163 | 164 | ```java 165 | public static int[][] chunk(int[] numbers, int size) { 166 | return IntStream.iterate(0, i -> i + size) 167 | .limit((long) Math.ceil((double) numbers.length / size)) 168 | .mapToObj(cur -> Arrays.copyOfRange(numbers, cur, cur + size > numbers.length ? numbers.length : cur + size)) 169 | .toArray(int[][]::new); 170 | } 171 | ``` 172 | 173 |
[⬆ 回到顶部](#目录) 174 | 175 | ### concat 176 | 177 | ```java 178 | public static T[] concat(T[] first, T[] second) { 179 | return Stream.concat( 180 | Stream.of(first), 181 | Stream.of(second) 182 | ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 183 | } 184 | ``` 185 | 186 |
[⬆ 回到顶部](#目录) 187 | 188 | ### countOccurrences 189 | 190 | 计算数组中某个值出现的次数。 191 | 192 | 使用 `Arrays.stream().filter().count()` 计算等于指定值的值的总数。 193 | 194 | ```java 195 | public static long countOccurrences(int[] numbers, int value) { 196 | return Arrays.stream(numbers) 197 | .filter(number -> number == value) 198 | .count(); 199 | } 200 | ``` 201 | 202 |
[⬆ 回到顶部](#目录) 203 | 204 | ### deepFlatten 205 | 206 | 数组扁平化。 207 | 208 | 使用递归实现,`Arrays.stream().flatMapToInt()` 209 | 210 | ```java 211 | public static int[] deepFlatten(Object[] input) { 212 | return Arrays.stream(input) 213 | .flatMapToInt(o -> { 214 | if (o instanceof Object[]) { 215 | return Arrays.stream(deepFlatten((Object[]) o)); 216 | } 217 | return IntStream.of((Integer) o); 218 | }).toArray(); 219 | } 220 | ``` 221 | 222 |
[⬆ 回到顶部](#目录) 223 | 224 | ### difference 225 | 226 | 返回两个数组之间的差异。 227 | 228 | 从 b 中创建一个集合,然后在 a 上使用 `Arrays.stream().filter()` 只保留 b 中不包含的值。 229 | 230 | ```java 231 | public static int[] difference(int[] first, int[] second) { 232 | Set set = Arrays.stream(second).boxed().collect(Collectors.toSet()); 233 | return Arrays.stream(first) 234 | .filter(v -> !set.contains(v)) 235 | .toArray(); 236 | } 237 | ``` 238 | 239 |
[⬆ 回到顶部](#目录) 240 | 241 | ### differenceWith 242 | 243 | 从比较器函数不返回true的数组中筛选出所有值。 244 | 245 | int的比较器是使用IntbinaryPerator函数来实现的。 246 | 247 | 使用 `Arrays.stream().filter()` 和 `Arrays.stream().noneMatch()` 查找相应的值。 248 | 249 | ```java 250 | public static int[] differenceWith(int[] first, int[] second, IntBinaryOperator comparator) { 251 | return Arrays.stream(first) 252 | .filter(a -> 253 | Arrays.stream(second) 254 | .noneMatch(b -> comparator.applyAsInt(a, b) == 0) 255 | ).toArray(); 256 | } 257 | ``` 258 | 259 |
[⬆ 回到顶部](#目录) 260 | 261 | ### distinctValuesOfArray 262 | 263 | 返回数组的所有不同值。 264 | 265 | 使用 `Arrays.stream().distinct()` 去除所有重复的值。 266 | 267 | ```java 268 | public static int[] distinctValuesOfArray(int[] elements) { 269 | return Arrays.stream(elements).distinct().toArray(); 270 | } 271 | ``` 272 | 273 |
[⬆ 回到顶部](#目录) 274 | 275 | ### dropElements 276 | 277 | 移除数组中的元素,直到传递的函数返回true为止。返回数组中的其余元素。 278 | 279 | 使用数组循环遍历数组,将数组的第一个元素删除,直到函数返回的值为真为止。返回其余的元素。 280 | 281 | ```java 282 | public static int[] dropElements(int[] elements, IntPredicate condition) { 283 | while (elements.length > 0 && !condition.test(elements[0])) { 284 | elements = Arrays.copyOfRange(elements, 1, elements.length); 285 | } 286 | return elements; 287 | } 288 | ``` 289 | 290 |
[⬆ 回到顶部](#目录) 291 | 292 | ### dropRight 293 | 294 | 返回一个新数组,从右边移除n个元素。 295 | 296 | 检查n是否短于给定的数组,并使用 `Array.copyOfRange()` 以便对其进行相应的切片或返回一个空数组。 297 | 298 | ```java 299 | public static int[] dropRight(int[] elements, int n) { 300 | if (n < 0) { 301 | throw new IllegalArgumentException("n is less than 0"); 302 | } 303 | return n < elements.length 304 | ? Arrays.copyOfRange(elements, 0, elements.length - n) 305 | : new int[0]; 306 | } 307 | ``` 308 | 309 |
[⬆ 回到顶部](#目录) 310 | 311 | ### everyNth 312 | 313 | 返回数组中的每个第n个元素。 314 | 315 | 使用 `IntStream.range().filter()` 创建一个新数组,该数组包含给定数组的每个第n个元素。 316 | 317 | ```java 318 | public static int[] everyNth(int[] elements, int nth) { 319 | return IntStream.range(0, elements.length) 320 | .filter(i -> i % nth == nth - 1) 321 | .map(i -> elements[i]) 322 | .toArray(); 323 | } 324 | ``` 325 | 326 |
[⬆ 回到顶部](#目录) 327 | 328 | ### indexOf 329 | 330 | 查找数组中元素的索引,在不存在元素的情况下返回-1。 331 | 332 | 使用 `IntStream.range().filter()` 查找数组中元素的索引。 333 | 334 | ```java 335 | public static int indexOf(int[] elements, int el) { 336 | return IntStream.range(0, elements.length) 337 | .filter(idx -> elements[idx] == el) 338 | .findFirst() 339 | .orElse(-1); 340 | } 341 | ``` 342 | 343 |
[⬆ 回到顶部](#目录) 344 | 345 | ### lastIndexOf 346 | 347 | 查找数组中元素的最后索引,在不存在元素的情况下返回-1。 348 | 349 | 使用 `IntStream.iterate().limit().filter()` 查找数组中元素的索引。 350 | 351 | ```java 352 | public static int lastIndexOf(int[] elements, int el) { 353 | return IntStream.iterate(elements.length - 1, i -> i - 1) 354 | .limit(elements.length) 355 | .filter(idx -> elements[idx] == el) 356 | .findFirst() 357 | .orElse(-1); 358 | } 359 | ``` 360 | 361 |
[⬆ 回到顶部](#目录) 362 | 363 | ### filterNonUnique 364 | 365 | 筛选出数组中的非唯一值。 366 | 367 | 对只包含唯一值的数组使用 `Arrays.stream().filter()`。 368 | 369 | ```java 370 | public static int[] filterNonUnique(int[] elements) { 371 | return Arrays.stream(elements) 372 | .filter(el -> indexOf(elements, el) != lastIndexOf(elements, el)) 373 | .distinct() 374 | .toArray(); 375 | } 376 | ``` 377 | 378 |
[⬆ 回到顶部](#目录) 379 | 380 | ### flatten 381 | 382 | 使数组扁平。 383 | 384 | 使用 `Arrays.stream().flatMapToInt().toArray()` 创建一个新数组。 385 | 386 | ```java 387 | public static int[] flatten(Object[] elements) { 388 | return Arrays.stream(elements) 389 | .flatMapToInt(el -> el instanceof int[] 390 | ? Arrays.stream((int[]) el) 391 | : IntStream.of((int) el) 392 | ).toArray(); 393 | } 394 | ``` 395 | 396 |
[⬆ 回到顶部](#目录) 397 | 398 | ### flattenDepth 399 | 400 | 将数组压平到指定的深度。 401 | 402 | ```java 403 | public static Object[] flattenDepth(Object[] elements, int depth) { 404 | if (depth == 0) { 405 | return elements; 406 | } 407 | return Arrays.stream(elements) 408 | .flatMap(el -> el instanceof Object[] 409 | ? Arrays.stream(flattenDepth((Object[]) el, depth - 1)) 410 | : Arrays.stream(new Object[]{el}) 411 | ).toArray(); 412 | 413 | 414 | } 415 | ``` 416 | 417 |
[⬆ 回到顶部](#目录) 418 | 419 | ### groupBy 420 | 421 | 根据给定函数对数组元素进行分组。 422 | 423 | 使用 `Arrays.stream().collect(Collectors.groupingBy())` 分组。 424 | 425 | ```java 426 | public static Map> groupBy(T[] elements, Function func) { 427 | return Arrays.stream(elements).collect(Collectors.groupingBy(func)); 428 | } 429 | ``` 430 | 431 |
[⬆ 回到顶部](#目录) 432 | 433 | ### initial 434 | 435 | 返回数组中除去最后一个的所有元素。 436 | 437 | 使用 `Arrays.copyOfRange()` 返回除最后一个之外的所有元素。 438 | 439 | ```java 440 | public static T[] initial(T[] elements) { 441 | return Arrays.copyOfRange(elements, 0, elements.length - 1); 442 | } 443 | ``` 444 | 445 |
[⬆ 回到顶部](#目录) 446 | 447 | ### initializeArrayWithRange 448 | 449 | 初始化一个数组,该数组包含在指定范围内的数字,传入 `start` 和 `end`。 450 | 451 | ```java 452 | public static int[] initializeArrayWithRange(int end, int start) { 453 | return IntStream.rangeClosed(start, end).toArray(); 454 | } 455 | ``` 456 | 457 |
[⬆ 回到顶部](#目录) 458 | 459 | ### initializeArrayWithValues 460 | 461 | 使用指定的值初始化并填充数组。 462 | 463 | ```java 464 | public static int[] initializeArrayWithValues(int n, int value) { 465 | return IntStream.generate(() -> value).limit(n).toArray(); 466 | } 467 | ``` 468 | 469 |
[⬆ 回到顶部](#目录) 470 | 471 | ### intersection 472 | 473 | 返回两个数组中存在的元素列表。 474 | 475 | 从第二步创建一个集合,然后在 a 上使用 `Arrays.stream().filter()` 来保存包含在 b 中的值。 476 | 477 | ```java 478 | public static int[] intersection(int[] first, int[] second) { 479 | Set set = Arrays.stream(second).boxed().collect(Collectors.toSet()); 480 | return Arrays.stream(first) 481 | .filter(set::contains) 482 | .toArray(); 483 | } 484 | ``` 485 | 486 |
[⬆ 回到顶部](#目录) 487 | 488 | ### isSorted 489 | 490 | 如果数组按升序排序,则返回 `1`,如果数组按降序排序,返回 `-1`,如果没有排序,则返回 `0`。 491 | 492 | 计算前两个元素的排序 `direction`。使用for循环对数组进行迭代,并对它们进行成对比较。如果 `direction` 发生变化,则返回 `0`, 493 | 如果到达最后一个元素,则返回 `direction`。 494 | 495 | ```java 496 | public static > int isSorted(T[] arr) { 497 | final int direction = arr[0].compareTo(arr[1]) < 0 ? 1 : -1; 498 | for (int i = 0; i < arr.length; i++) { 499 | T val = arr[i]; 500 | if (i == arr.length - 1) return direction; 501 | else if ((val.compareTo(arr[i + 1]) * direction > 0)) return 0; 502 | } 503 | return direction; 504 | } 505 | ``` 506 | 507 |
[⬆ 回到顶部](#目录) 508 | 509 | ### join 510 | 511 | 将数组的所有元素连接到字符串中,并返回此字符串。 512 | 513 | 使用 `IntStream.range` 创建一个指定索引的数组。然后,使用 `Stream.reduce` 将元素组合成字符串。 514 | 515 | ```java 516 | public static String join(T[] arr, String separator, String end) { 517 | return IntStream.range(0, arr.length) 518 | .mapToObj(i -> new SimpleEntry<>(i, arr[i])) 519 | .reduce("", (acc, val) -> val.getKey() == arr.length - 2 520 | ? acc + val.getValue() + end 521 | : val.getKey() == arr.length - 1 ? acc + val.getValue() : acc + val.getValue() + separator, (fst, snd) -> fst); 522 | } 523 | ``` 524 | 525 |
[⬆ 回到顶部](#目录) 526 | 527 | ### nthElement 528 | 529 | 返回数组的第n个元素。 530 | 531 | Use `Arrays.copyOfRange()` 优先得到包含第n个元素的数组。 532 | 533 | ```Java 534 | public static T nthElement(T[] arr, int n) { 535 | if (n > 0) { 536 | return Arrays.copyOfRange(arr, n, arr.length)[0]; 537 | } 538 | return Arrays.copyOfRange(arr, arr.length + n, arr.length)[0]; 539 | } 540 | ``` 541 | 542 |
[⬆ 回到顶部](#目录) 543 | 544 | ### pick 545 | 546 | 从对象中选择与给定键对应的键值对。 547 | 548 | 使用 `Arrays.stream` 过滤 `arr` 中存在的所有键。然后,使用 `Collectors.toMap` 将所有的key转换为Map。 549 | 550 | ```java 551 | public static Map pick(Map obj, T[] arr) { 552 | return Arrays.stream(arr) 553 | .filter(obj::containsKey) 554 | .collect(Collectors.toMap(k -> k, obj::get)); 555 | } 556 | ``` 557 | 558 |
[⬆ 回到顶部](#目录) 559 | 560 | ### reducedFilter 561 | 562 | 根据条件筛选对象数组,同时筛选出未指定的键。 563 | 564 | 使用 `Arrays.stream().filter()` 根据谓词 `fn` 过滤数组,以便返回条件为真的对象。 565 | 对于每个过滤的Map对象,创建一个新的Map,其中包含 `keys` 中的键。最后,将Map对象收集到一个数组中。 566 | 567 | ```java 568 | public static Map[] reducedFilter(Map[] data, String[] keys, Predicate> fn) { 569 | return Arrays.stream(data) 570 | .filter(fn) 571 | .map(el -> Arrays.stream(keys).filter(el::containsKey) 572 | .collect(Collectors.toMap(Function.identity(), el::get))) 573 | .toArray((IntFunction[]>) Map[]::new); 574 | } 575 | ``` 576 | 577 |
[⬆ 回到顶部](#目录) 578 | 579 | ### sample 580 | 581 | 从数组中返回一个随机元素。 582 | 583 | 使用 `Math.Randoman()` 生成一个随机数,然后将它乘以数组的 `length`,然后使用 `Math.floor()` 获得一个最近的整数,该方法也适用于字符串。 584 | 585 | ```java 586 | public static T sample(T[] arr) { 587 | return arr[(int) Math.floor(Math.random() * arr.length)]; 588 | } 589 | ``` 590 | 591 |
[⬆ 回到顶部](#目录) 592 | 593 | ### sampleSize 594 | 595 | 从 `array` 到 `array` 大小的唯一键获取 `n` 个随机元素。 596 | 597 | 根据[Fisher-Yates算法](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle),使用 `Array.copyOfRange()` 获得优先的 `n` 个元素。 598 | 599 | ```java 600 | public static T[] sampleSize(T[] input, int n) { 601 | T[] arr = Arrays.copyOf(input, input.length); 602 | int length = arr.length; 603 | int m = length; 604 | while (m > 0) { 605 | int i = (int) Math.floor(Math.random() * m--); 606 | T tmp = arr[i]; 607 | arr[i] = arr[m]; 608 | arr[m] = tmp; 609 | } 610 | return Arrays.copyOfRange(arr, 0, n > length ? length : n); 611 | } 612 | ``` 613 | 614 |
[⬆ 回到顶部](#目录) 615 | 616 | ### shuffle 617 | 618 | 将数组值的顺序随机化,返回一个新数组。 619 | 620 | 根据 [Fisher-Yates 算法](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) 重新排序数组的元素。 621 | 622 | ```java 623 | public static T[] shuffle(T[] input) { 624 | T[] arr = Arrays.copyOf(input, input.length); 625 | int length = arr.length; 626 | int m = length; 627 | while (m > 0) { 628 | int i = (int) Math.floor(Math.random() * m--); 629 | T tmp = arr[i]; 630 | arr[i] = arr[m]; 631 | arr[m] = tmp; 632 | } 633 | return arr; 634 | } 635 | ``` 636 | 637 |
[⬆ 回到顶部](#目录) 638 | 639 | ### similarity 640 | 641 | 返回出现在两个数组中的元素数组。 642 | 643 | 使用 `Arrays.stream().filter()` 移除,然后使用 `Arrays.stream().anyMatch()` 匹配 `second` 部分的值。 644 | 645 | ```java 646 | public static T[] similarity(T[] first, T[] second) { 647 | return Arrays.stream(first) 648 | .filter(a -> Arrays.stream(second).anyMatch(b -> Objects.equals(a, b))) 649 | // Make a new array of first's runtime type, but empty content: 650 | .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 651 | } 652 | ``` 653 | 654 |
[⬆ 回到顶部](#目录) 655 | 656 | ### sortedIndex 657 | 658 | 返回值应该插入到数组中的最低索引,以保持其排序顺序。 659 | 660 | 检查数组是否按降序(松散地)排序。 使用 `IntStream.range().filter()` 来找到元素应该被插入的合适的索引。 661 | 662 | ```java 663 | public static > int sortedIndex(T[] arr, T el) { 664 | boolean isDescending = arr[0].compareTo(arr[arr.length - 1]) > 0; 665 | return IntStream.range(0, arr.length) 666 | .filter(i -> isDescending ? el.compareTo(arr[i]) >= 0 : el.compareTo(arr[i]) <= 0) 667 | .findFirst() 668 | .orElse(arr.length); 669 | } 670 | ``` 671 | 672 |
[⬆ 回到顶部](#目录) 673 | 674 | ### symmetricDifference 675 | 676 | 返回两个数组之间的对称差异。 677 | 678 | 从每个数组中创建一个 `Set`,然后使用 `Arrays.stream().filter()` 来保持其他值不包含的值。最后,连接两个数组并创建一个新数组并返回。 679 | 680 | ```java 681 | public static T[] symmetricDifference(T[] first, T[] second) { 682 | Set sA = new HashSet<>(Arrays.asList(first)); 683 | Set sB = new HashSet<>(Arrays.asList(second)); 684 | 685 | return Stream.concat( 686 | Arrays.stream(first).filter(a -> !sB.contains(a)), 687 | Arrays.stream(second).filter(b -> !sA.contains(b)) 688 | ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass())); 689 | } 690 | ``` 691 | 692 |
[⬆ 回到顶部](#目录) 693 | 694 | ### tail 695 | 696 | 返回数组中除第一个元素外的所有元素。 697 | 698 | 如果数组的长度大于1,则返回 `Arrays.copyOfRange(1)`,否则返回整个数组。 699 | 700 | ```java 701 | public static T[] tail(T[] arr) { 702 | return arr.length > 1 703 | ? Arrays.copyOfRange(arr, 1, arr.length) 704 | : arr; 705 | } 706 | ``` 707 | 708 |
[⬆ 回到顶部](#目录) 709 | 710 | ### take 711 | 712 | 返回一个从开头删除n个元素的数组。 713 | 714 | ```java 715 | public static T[] take(T[] arr, int n) { 716 | return Arrays.copyOfRange(arr, 0, n); 717 | } 718 | ``` 719 | 720 |
[⬆ 回到顶部](#目录) 721 | 722 | ### takeRight 723 | 724 | 返回从末尾移除n个元素的数组。 725 | 726 | 使用 `Arrays.copyOfRange()` 用从末尾取来的 `N` 个元素来创建一个数组。 727 | 728 | ```java 729 | public static T[] takeRight(T[] arr, int n) { 730 | return Arrays.copyOfRange(arr, arr.length - n, arr.length); 731 | } 732 | ``` 733 | 734 |
[⬆ 回到顶部](#目录) 735 | 736 | ### union 737 | 738 | 返回两个数组中任何一个中存在的每个元素一次。 739 | 740 | 使用 `a` 和 `b` 的所有值创建一个 `Set`,并将其转换为数组。 741 | 742 | ```Java 743 | public static T[] union(T[] first, T[] second) { 744 | Set set = new HashSet<>(Arrays.asList(first)); 745 | set.addAll(Arrays.asList(second)); 746 | return set.toArray((T[]) Arrays.copyOf(new Object[0], 0, first.getClass())); 747 | } 748 | ``` 749 | 750 |
[⬆ 回到顶部](#目录) 751 | 752 | ### without 753 | 754 | 筛选出具有指定值之一的数组的元素。 755 | 756 | 使用 `Arrays.strean().filter()` 创建一个数组,排除(使用 `!Arrays.asList(elements).contains()`)所有命中的值。 757 | 758 | ```java 759 | public static T[] without(T[] arr, T... elements) { 760 | List excludeElements = Arrays.asList(elements); 761 | return Arrays.stream(arr) 762 | .filter(el -> !excludeElements.contains(el)) 763 | .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, arr.getClass())); 764 | } 765 | ``` 766 | 767 |
[⬆ 回到顶部](#目录) 768 | 769 | ### zip 770 | 771 | 根据原始数组中的位置创建元素数组。 772 | 773 | ```java 774 | public static List zip(Object[]... arrays) { 775 | OptionalInt max = Arrays.stream(arrays).mapToInt(arr -> arr.length).max(); 776 | return IntStream.range(0, max.getAsInt()) 777 | .mapToObj(i -> Arrays.stream(arrays) 778 | .map(arr -> i < arr.length ? arr[i] : null) 779 | .toArray()) 780 | .collect(Collectors.toList()); 781 | } 782 | ``` 783 | 784 |
[⬆ 回到顶部](#目录) 785 | 786 | ### zipObject 787 | 788 | 给定有效的属性标识符数组和值数组,返回将属性与值关联的对象。 789 | 790 | ```java 791 | public static Map zipObject(String[] props, Object[] values) { 792 | return IntStream.range(0, props.length) 793 | .mapToObj(i -> new SimpleEntry<>(props[i], i < values.length ? values[i] : null)) 794 | .collect( 795 | HashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), HashMap::putAll); 796 | } 797 | ``` 798 | 799 |
[⬆ 回到顶部](#目录) 800 | 801 | ## Maths 802 | 803 | ### average 804 | 805 | 返回两个或两个以上数字的平均值。 806 | 807 | ```java 808 | public static double average(int[] arr) { 809 | return IntStream.of(arr) 810 | .average() 811 | .orElseThrow(() -> new IllegalArgumentException("Array is empty")); 812 | } 813 | ``` 814 | 815 |
[⬆ 回到顶部](#目录) 816 | 817 | ### gcd 818 | 819 | 计算一系列数字的最大公约数(gcd)。 820 | 821 | 使用 `Arrays.stream().reduce()` 和 GCD(使用递归公式)计算一组数字的最大公约数。 822 | 823 | ```java 824 | public static OptionalInt gcd(int[] numbers) { 825 | return Arrays.stream(numbers) 826 | .reduce((a, b) -> gcd(a, b)); 827 | } 828 | 829 | private static int gcd(int a, int b) { 830 | if (b == 0) { 831 | return a; 832 | } 833 | return gcd(b, a % b); 834 | } 835 | ``` 836 | 837 |
[⬆ 回到顶部](#目录) 838 | 839 | ### lcm 840 | 841 | 计算数字数组的最低公共倍数(LCM)。 842 | 843 | 使用 `Arrays.stream().reduce()` 和 LCM公式(使用递归)来计算数字数组的最低公共倍数。 844 | 845 | ```java 846 | public static OptionalInt lcm(int[] numbers) { 847 | IntBinaryOperator lcm = (x, y) -> (x * y) / gcd(x, y); 848 | return Arrays.stream(numbers) 849 | .reduce((a, b) -> lcm.applyAsInt(a, b)); 850 | } 851 | 852 | private static int gcd(int a, int b) { 853 | if (b == 0) { 854 | return a; 855 | } 856 | return gcd(b, a % b); 857 | } 858 | ``` 859 | 860 |
[⬆ 回到顶部](#目录) 861 | 862 | ### findNextPositivePowerOfTwo 863 | 864 | 查找大于或等于该值的下一个幂。 865 | 866 | 该方法使用左移运算符将1与右侧的值位移。右侧使用 `Integer.numberOfLeadingZeros`方法。 867 | `001 << 2` would be `100`. `100` in decimal is equal to `4`. 868 | 869 | `Integer.numberOfLeadingZeros` 给出了数值前导零的数目。例如,调用 `Integer.numberOfLeadingZeros(3)` 将赋值为30。 870 | 这是因为3在二进制中表示为 `11`。由于整数有32位,所以有30位有0位。左移运算符的右边变为 `32-30 = 2`。 871 | 左移1,即 `001 << 2` 将是 `100`,十进制中的 `100` 等于 `4`。 872 | 873 | ```java 874 | public static int findNextPositivePowerOfTwo(int value) { 875 | return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); 876 | } 877 | ``` 878 | 879 |
[⬆ 回到顶部](#目录) 880 | 881 | ### isEven 882 | 883 | 检查数字是否是偶数。 884 | 885 | 这个方法使用按位运算符,`0b1` 是1的二进制表示。 886 | 因为Java 7可以通过用 `0b` 或 `0B` 作为前缀来编写二进制文字。 887 | 数字为偶数时,`&` 运算符将返回0。 例如,`IsEven(4)` 会导致 `100` `&` `001`,`&` 的结果将是 `000`。 888 | 889 | ```java 890 | public static boolean isEven(final int value) { 891 | return (value & 0b1) == 0; 892 | } 893 | ``` 894 | 895 |
[⬆ 回到顶部](#目录) 896 | 897 | ### isPowerOfTwo 898 | 899 | 检查一个值是2的正幂。 900 | 901 | 为了理解它是如何工作的,让我们假设我们调用了 `IsPowerOfTwo(4)`。 902 | 903 | 当值大于0时,将评估 `&&` 运算符的右侧。 904 | 905 | `(~value + 1)` 的结果等于值本身,`~100 + 001` => `011 + 001` => `100`。 906 | 907 | `(value & value)` 的结果是value,`100` & `100` => `100`.。 908 | 909 | 当值等于值时,这将把值表达为真值。 910 | 911 | ```Java 912 | public static boolean isPowerOfTwo(final int value) { 913 | return value > 0 && ((value & (~value + 1)) == value); 914 | } 915 | ``` 916 | 917 |
[⬆ 回到顶部](#目录) 918 | 919 | ### generateRandomInt 920 | 921 | 生成一个介于 `Integer.MIN_VALUE` 和 `Integer.MAX_VALUE` 之间的随机数。 922 | 923 | ```java 924 | public static int generateRandomInt() { 925 | return ThreadLocalRandom.current().nextInt(); 926 | } 927 | ``` 928 | 929 |
[⬆ 回到顶部](#目录) 930 | 931 | ## String 932 | 933 | ### anagrams 934 | 935 | 生成一个字符串的所有字符(包含重复)。 936 | 937 | ```java 938 | public static List anagrams(String input) { 939 | if (input.length() <= 2) { 940 | return input.length() == 2 941 | ? Arrays.asList(input, input.substring(1) + input.substring(0, 1)) 942 | : Collections.singletonList(input); 943 | } 944 | return IntStream.range(0, input.length()) 945 | .mapToObj(i -> new SimpleEntry<>(i, input.substring(i, i + 1))) 946 | .flatMap(entry -> 947 | anagrams(input.substring(0, entry.getKey()) + input.substring(entry.getKey() + 1)) 948 | .stream() 949 | .map(s -> entry.getValue() + s)) 950 | .collect(Collectors.toList()); 951 | } 952 | ``` 953 | 954 |
[⬆ 回到顶部](#目录) 955 | 956 | ### byteSize 957 | 958 | 以字节为单位返回字符串的长度。 959 | 960 | ```java 961 | public static int byteSize(String input) { 962 | return input.getBytes().length; 963 | } 964 | ``` 965 | 966 |
[⬆ 回到顶部](#目录) 967 | 968 | ### capitalize 969 | 970 | 将字符串首字母大写。 971 | 972 | ```Java 973 | public static String capitalize(String input, boolean lowerRest) { 974 | return input.substring(0, 1).toUpperCase() + 975 | (lowerRest 976 | ? input.substring(1, input.length()).toLowerCase() 977 | : input.substring(1, input.length())); 978 | } 979 | ``` 980 | 981 |
[⬆ 回到顶部](#目录) 982 | 983 | ### capitalizeEveryWord 984 | 985 | 将字符串中每个单词的首字母大写。 986 | 987 | ```java 988 | public static String capitalizeEveryWord(final String input) { 989 | return Pattern.compile("\\b(?=\\w)").splitAsStream(input) 990 | .map(w -> capitalize(w, false)) 991 | .collect(Collectors.joining()); 992 | } 993 | ``` 994 | 995 |
[⬆ 回到顶部](#目录) 996 | 997 | ### countVowels 998 | 999 | 在提供的字符串中返回元音的个数。 1000 | 1001 | ```java 1002 | public static int countVowels(String input) { 1003 | return input.replaceAll("[^aeiouAEIOU]", "").length(); 1004 | } 1005 | ``` 1006 | 1007 |
[⬆ 回到顶部](#目录) 1008 | 1009 | ### escapeRegExp 1010 | 1011 | 转义要在正则表达式中使用的字符串。 1012 | 1013 | ```java 1014 | public static String escapeRegExp(String input) { 1015 | return Pattern.quote(input); 1016 | } 1017 | ``` 1018 | 1019 |
[⬆ 回到顶部](#目录) 1020 | 1021 | ### fromCamelCase 1022 | 1023 | 从驼峰式转换字符串。 1024 | 1025 | ```java 1026 | public static String fromCamelCase(String input, String separator) { 1027 | return input 1028 | .replaceAll("([a-z\\d])([A-Z])", "$1" + separator + "$2") 1029 | .toLowerCase(); 1030 | } 1031 | ``` 1032 | 1033 |
[⬆ 回到顶部](#目录) 1034 | 1035 | ### isAbsoluteUrl 1036 | 1037 | 如果给定的字符串是绝对URL,则返回 `true`,否则返回 `false`。 1038 | 1039 | ```java 1040 | public static boolean isAbsoluteUrl(String url) { 1041 | return Pattern.compile("^[a-z][a-z0-9+.-]*:").matcher(url).find(); 1042 | } 1043 | ``` 1044 | 1045 |
[⬆ 回到顶部](#目录) 1046 | 1047 | ### isLowerCase 1048 | 1049 | 检查字符串是否为小写。 1050 | 1051 | ```java 1052 | public static boolean isLowerCase(String input) { 1053 | return Objects.equals(input, input.toLowerCase()); 1054 | } 1055 | ``` 1056 | 1057 |
[⬆ 回到顶部](#目录) 1058 | 1059 | ### isUpperCase 1060 | 1061 | 检查字符串是否为大写。 1062 | 1063 | ```java 1064 | public static boolean isUpperCase(String input) { 1065 | return Objects.equals(input, input.toUpperCase()); 1066 | } 1067 | ``` 1068 | 1069 |
[⬆ 回到顶部](#目录) 1070 | 1071 | ### isPalindrome 1072 | 1073 | 判断一个字符串是否回文。 1074 | 1075 | ```java 1076 | public static boolean isPalindrome(String input) { 1077 | String s = input.toLowerCase().replaceAll("[\\W_]", ""); 1078 | return Objects.equals( 1079 | s, 1080 | new StringBuilder(s).reverse().toString() 1081 | ); 1082 | } 1083 | ``` 1084 | 1085 |
[⬆ 回到顶部](#目录) 1086 | 1087 | ### isNumeric 1088 | 1089 | 检查字符串是否为数字。 1090 | 1091 | ```java 1092 | public static boolean isNumeric(final String input) { 1093 | return IntStream.range(0, input.length()) 1094 | .allMatch(i -> Character.isDigit(input.charAt(i))); 1095 | } 1096 | ``` 1097 | 1098 |
[⬆ 回到顶部](#目录) 1099 | 1100 | ### mask 1101 | 1102 | 用指定的掩码字符替换除最后 `num` 个字符以外的所有字符。 1103 | 1104 | ```Java 1105 | public static String mask(String input, int num, String mask) { 1106 | int length = input.length(); 1107 | return num > 0 1108 | ? 1109 | input.substring(0, length - num).replaceAll(".", mask) 1110 | + input.substring(length - num) 1111 | : 1112 | input.substring(0, Math.negateExact(num)) 1113 | + input.substring(Math.negateExact(num), length).replaceAll(".", mask); 1114 | } 1115 | ``` 1116 | 1117 |
[⬆ 回到顶部](#目录) 1118 | 1119 | ### reverseString 1120 | 1121 | 反转字符串。 1122 | 1123 | ```java 1124 | public static String reverseString(String input) { 1125 | return new StringBuilder(input).reverse().toString(); 1126 | } 1127 | ``` 1128 | 1129 |
[⬆ 回到顶部](#目录) 1130 | 1131 | ### sortCharactersInString 1132 | 1133 | 按字母顺序排列字符串中的字符。 1134 | 1135 | ```java 1136 | public static String sortCharactersInString(String input) { 1137 | return Arrays.stream(input.split("")).sorted().collect(Collectors.joining()); 1138 | } 1139 | ``` 1140 | 1141 |
[⬆ 回到顶部](#目录) 1142 | 1143 | ### splitLines 1144 | 1145 | 将多行字符串拆分为行数组。 1146 | 1147 | ```java 1148 | public static String[] splitLines(String input) { 1149 | return input.split("\\r?\\n"); 1150 | } 1151 | ``` 1152 | 1153 |
[⬆ 回到顶部](#目录) 1154 | 1155 | ### toCamelCase 1156 | 1157 | 转换一个字符串为驼峰式。 1158 | 1159 | ```java 1160 | public static String toCamelCase(String input) { 1161 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 1162 | List matchedParts = new ArrayList<>(); 1163 | while (matcher.find()) { 1164 | matchedParts.add(matcher.group(0)); 1165 | } 1166 | String s = matchedParts.stream() 1167 | .map(x -> x.substring(0, 1).toUpperCase() + x.substring(1).toLowerCase()) 1168 | .collect(Collectors.joining()); 1169 | return s.substring(0, 1).toLowerCase() + s.substring(1); 1170 | } 1171 | ``` 1172 | 1173 |
[⬆ 回到顶部](#目录) 1174 | 1175 | ### toKebabCase 1176 | 1177 | 将字符串转换为kebab大小写。 1178 | 1179 | ```java 1180 | public static String toKebabCase(String input) { 1181 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 1182 | List matchedParts = new ArrayList<>(); 1183 | while (matcher.find()) { 1184 | matchedParts.add(matcher.group(0)); 1185 | } 1186 | return matchedParts.stream() 1187 | .map(String::toLowerCase) 1188 | .collect(Collectors.joining("-")); 1189 | } 1190 | ``` 1191 | 1192 |
[⬆ 回到顶部](#目录) 1193 | 1194 | ### match 1195 | 1196 | 正则匹配。 1197 | 1198 | ```java 1199 | public static List match(String input, String regex) { 1200 | Matcher matcher = Pattern.compile(regex).matcher(input); 1201 | List matchedParts = new ArrayList<>(); 1202 | while (matcher.find()) { 1203 | matchedParts.add(matcher.group(0)); 1204 | } 1205 | return matchedParts; 1206 | } 1207 | ``` 1208 | 1209 |
[⬆ 回到顶部](#目录) 1210 | 1211 | ### toSnakeCase 1212 | 1213 | 将字符串转换为蛇形小写,如 `Im_Biezhi`。 1214 | 1215 | ```java 1216 | public static String toSnakeCase(String input) { 1217 | Matcher matcher = Pattern.compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+").matcher(input); 1218 | List matchedParts = new ArrayList<>(); 1219 | while (matcher.find()) { 1220 | matchedParts.add(matcher.group(0)); 1221 | } 1222 | return matchedParts.stream() 1223 | .map(String::toLowerCase) 1224 | .collect(Collectors.joining("_")); 1225 | } 1226 | ``` 1227 | 1228 |
[⬆ 回到顶部](#目录) 1229 | 1230 | ### truncateString 1231 | 1232 | 将字符串截断到指定的长度。 1233 | 1234 | ```java 1235 | public static String truncateString(String input, int num) { 1236 | return input.length() > num 1237 | ? input.substring(0, num > 3 ? num - 3 : num) + "..." 1238 | : input; 1239 | } 1240 | ``` 1241 | 1242 |
[⬆ 回到顶部](#目录) 1243 | 1244 | ### words 1245 | 1246 | 将给定的字符串转换为单词数组。 1247 | 1248 | ```Java 1249 | public static String[] words(String input) { 1250 | return Arrays.stream(input.split("[^a-zA-Z-]+")) 1251 | .filter(s -> !s.isEmpty()) 1252 | .toArray(String[]::new); 1253 | } 1254 | ``` 1255 | 1256 |
[⬆ 回到顶部](#目录) 1257 | 1258 | ### stringToIntegers 1259 | 1260 | 将由空格分隔的数字字符串转换为 int 数组。 1261 | 1262 | ```Java 1263 | public static int[] stringToIntegers(String numbers) { 1264 | return Arrays.stream(numbers.split(" ")).mapToInt(Integer::parseInt).toArray(); 1265 | } 1266 | ``` 1267 | 1268 |
[⬆ 回到顶部](#目录) 1269 | 1270 | ## IO 1271 | 1272 | ### convertInputStreamToString 1273 | 1274 | 将InputStream转换为字符串。 1275 | 1276 | ```java 1277 | public static String convertInputStreamToString(final InputStream in) throws IOException { 1278 | ByteArrayOutputStream result = new ByteArrayOutputStream(); 1279 | byte[] buffer = new byte[1024]; 1280 | int length; 1281 | while ((length = in.read(buffer)) != -1) { 1282 | result.write(buffer, 0, length); 1283 | } 1284 | return result.toString(StandardCharsets.UTF_8.name()); 1285 | } 1286 | ``` 1287 | 1288 |
[⬆ 回到顶部](#目录) 1289 | 1290 | ### readFileAsString 1291 | 1292 | 将文件内容读入字符串。 1293 | 1294 | ```java 1295 | public String readFileAsString(Path path) throws IOException { 1296 | return new String(Files.readAllBytes(path)); 1297 | } 1298 | ``` 1299 | 1300 |
[⬆ 回到顶部](#目录) 1301 | 1302 | ### getCurrentWorkingDirectoryPath 1303 | 1304 | 获取当前工作目录。 1305 | 1306 | ```java 1307 | public static String getCurrentWorkingDirectoryPath() { 1308 | return FileSystems.getDefault().getPath("").toAbsolutePath().toString(); 1309 | } 1310 | ``` 1311 | 1312 |
[⬆ 回到顶部](#目录) 1313 | 1314 | ### tmpDirName 1315 | 1316 | 返回 `java.io.tmpdir` 系统属性的值。如果末尾没有分隔符,则追加分隔符。 1317 | 1318 | ```java 1319 | public static String tmpDirName() { 1320 | String tmpDirName = System.getProperty("java.io.tmpdir"); 1321 | if (!tmpDirName.endsWith(File.separator)) { 1322 | tmpDirName += File.separator; 1323 | } 1324 | 1325 | return tmpDirName; 1326 | } 1327 | ``` 1328 | 1329 |
[⬆ 回到顶部](#目录) 1330 | 1331 | ## Exception 1332 | 1333 | ### stackTraceAsString 1334 | 1335 | 将异常堆栈跟踪转换为字符串。 1336 | 1337 | ```java 1338 | public static String stackTraceAsString(final Throwable throwable) { 1339 | final StringWriter sw = new StringWriter(); 1340 | throwable.printStackTrace(new PrintWriter(sw)); 1341 | return sw.toString(); 1342 | } 1343 | ``` 1344 | 1345 |
[⬆ 回到顶部](#目录) 1346 | 1347 | ## System 1348 | 1349 | ### osName 1350 | 1351 | 以小写字符串的形式获取操作系统的名称。 1352 | 1353 | ```java 1354 | public static String osName() { 1355 | return System.getProperty("os.name").toLowerCase(); 1356 | } 1357 | ``` 1358 | 1359 |
[⬆ 回到顶部](#目录) 1360 | 1361 | ### isDebuggerEnabled 1362 | 1363 | 检查JVM是否为debug模式。 1364 | 1365 | ```java 1366 | public static boolean isDebuggerAttached() { 1367 | final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); 1368 | return runtimeMXBean.getInputArguments() 1369 | .stream() 1370 | .anyMatch(arg -> arg.contains("-agentlib:jdwp")); 1371 | 1372 | } 1373 | ``` 1374 | 1375 |
[⬆ 回到顶部](#目录) 1376 | 1377 | ## Class 1378 | 1379 | ### getAllInterfaces 1380 | 1381 | 此方法返回由给定类及其超类实现的所有接口。 1382 | 1383 | 该方法通过连接两个Stream来工作。第一个Stream是通过创建带有接口的流和接口实现的所有接口来递归构建的。 1384 | 第二个Stream对超类也是如此。其结果是删除重复项后将两个Stream连接起来。 1385 | 1386 | ```java 1387 | public static List> getAllInterfaces(Class cls) { 1388 | return Stream.concat( 1389 | Arrays.stream(cls.getInterfaces()).flatMap(intf -> 1390 | Stream.concat(Stream.of(intf), getAllInterfaces(intf).stream())), 1391 | cls.getSuperclass() == null ? Stream.empty() : getAllInterfaces(cls.getSuperclass()).stream() 1392 | ).distinct().collect(Collectors.toList()); 1393 | } 1394 | ``` 1395 | 1396 |
[⬆ 回到顶部](#目录) 1397 | 1398 | ### isInnerClass 1399 | 1400 | 此方法检查指定的类是内部类还是静态嵌套类。 1401 | 1402 | ```Java 1403 | public static boolean isInnerClass(final Class cls) { 1404 | return cls != null && cls.getEnclosingClass() != null; 1405 | } 1406 | ``` 1407 | 1408 |
[⬆ 回到顶部](#目录) 1409 | 1410 | ## Enum 1411 | 1412 | ### getEnumMap 1413 | 1414 | 将枚举转换为 Map,其中 key 是枚举名,value 是枚举本身。 1415 | 1416 | ```java 1417 | public static > Map getEnumMap(final Class enumClass) { 1418 | return Arrays.stream(enumClass.getEnumConstants()) 1419 | .collect(Collectors.toMap(Enum::name, Function.identity())); 1420 | } 1421 | ``` 1422 | 1423 |
[⬆ 回到顶部](#目录) 1424 | --------------------------------------------------------------------------------