1 Star 2 Fork 1

angcyo / 30-seconds-of-java8

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
CC0-1.0

30 seconds of java8

License PRs Welcome Travis Build @biezhi on zhihu

你可以在30秒或更短时间内收集有用的Java8代码片段。

  • 使用 Ctrl + F 或者 command + F 来查找代码片段。
  • 代码片段基于 Java8,如果你还不熟悉可以在这里学习。
  • 代码片段翻译自 little-java-functions

目录

📚 Array (数组相关)

详细信息

➗ Math (数学相关)

详细信息

📜 String (字符串相关)

详细信息

⭕️ IO (IO流相关)

详细信息

❌ Exception (异常相关)

详细信息

🖥 System (系统相关)

详细信息

💡 Class (类相关)

详细信息

💎 Enum (枚举相关)

详细信息

Array

chunk

将数组分割成特定大小的小数组。

public static int[][] chunk(int[] numbers, int size) {
    return IntStream.iterate(0, i -> i + size)
            .limit((long) Math.ceil((double) numbers.length / size))
            .mapToObj(cur -> Arrays.copyOfRange(numbers, cur, cur + size > numbers.length ? numbers.length : cur + size))
            .toArray(int[][]::new);
}


⬆ 回到顶部

concat

public static <T> T[] concat(T[] first, T[] second) {
    return Stream.concat(
            Stream.of(first),
            Stream.of(second)
    ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass()));
}


⬆ 回到顶部

countOccurrences

计算数组中某个值出现的次数。

使用 Arrays.stream().filter().count() 计算等于指定值的值的总数。

public static long countOccurrences(int[] numbers, int value) {
    return Arrays.stream(numbers)
            .filter(number -> number == value)
            .count();
}


⬆ 回到顶部

deepFlatten

数组扁平化。

使用递归实现,Arrays.stream().flatMapToInt()

public static int[] deepFlatten(Object[] input) {
    return Arrays.stream(input)
            .flatMapToInt(o -> {
                if (o instanceof Object[]) {
                    return Arrays.stream(deepFlatten((Object[]) o));
                }
                return IntStream.of((Integer) o);
            }).toArray();
}


⬆ 回到顶部

difference

返回两个数组之间的差异。

从 b 中创建一个集合,然后在 a 上使用 Arrays.stream().filter() 只保留 b 中不包含的值。

public static int[] difference(int[] first, int[] second) {
    Set<Integer> set = Arrays.stream(second).boxed().collect(Collectors.toSet());
    return Arrays.stream(first)
            .filter(v -> !set.contains(v))
            .toArray();
}


⬆ 回到顶部

differenceWith

从比较器函数不返回true的数组中筛选出所有值。

int的比较器是使用IntbinaryPerator函数来实现的。

使用 Arrays.stream().filter()Arrays.stream().noneMatch() 查找相应的值。

public static int[] differenceWith(int[] first, int[] second, IntBinaryOperator comparator) {
    return Arrays.stream(first)
            .filter(a ->
                    Arrays.stream(second)
                            .noneMatch(b -> comparator.applyAsInt(a, b) == 0)
            ).toArray();
}


⬆ 回到顶部

distinctValuesOfArray

返回数组的所有不同值。

使用 Arrays.stream().distinct() 去除所有重复的值。

public static int[] distinctValuesOfArray(int[] elements) {
    return Arrays.stream(elements).distinct().toArray();
}


⬆ 回到顶部

dropElements

移除数组中的元素,直到传递的函数返回true为止。返回数组中的其余元素。

使用数组循环遍历数组,将数组的第一个元素删除,直到函数返回的值为真为止。返回其余的元素。

public static int[] dropElements(int[] elements, IntPredicate condition) {
    while (elements.length > 0 && !condition.test(elements[0])) {
        elements = Arrays.copyOfRange(elements, 1, elements.length);
    }
    return elements;
}


⬆ 回到顶部

dropRight

返回一个新数组,从右边移除n个元素。

检查n是否短于给定的数组,并使用 Array.copyOfRange() 以便对其进行相应的切片或返回一个空数组。

public static int[] dropRight(int[] elements, int n) {
    if (n < 0) {
        throw new IllegalArgumentException("n is less than 0");
    }
    return n < elements.length
            ? Arrays.copyOfRange(elements, 0, elements.length - n)
            : new int[0];
}


⬆ 回到顶部

everyNth

返回数组中的每个第n个元素。

使用 IntStream.range().filter() 创建一个新数组,该数组包含给定数组的每个第n个元素。

public static int[] everyNth(int[] elements, int nth) {
     return IntStream.range(0, elements.length)
             .filter(i -> i % nth == nth - 1)
             .map(i -> elements[i])
             .toArray();
 }


⬆ 回到顶部

indexOf

查找数组中元素的索引,在不存在元素的情况下返回-1。

使用 IntStream.range().filter() 查找数组中元素的索引。

public static int indexOf(int[] elements, int el) {
    return IntStream.range(0, elements.length)
            .filter(idx -> elements[idx] == el)
            .findFirst()
            .orElse(-1);
}


⬆ 回到顶部

lastIndexOf

查找数组中元素的最后索引,在不存在元素的情况下返回-1。

使用 IntStream.iterate().limit().filter() 查找数组中元素的索引。

public static int lastIndexOf(int[] elements, int el) {
    return IntStream.iterate(elements.length - 1, i -> i - 1)
            .limit(elements.length)
            .filter(idx -> elements[idx] == el)
            .findFirst()
            .orElse(-1);
}


⬆ 回到顶部

filterNonUnique

筛选出数组中的非唯一值。

对只包含唯一值的数组使用 Arrays.stream().filter()

public static int[] filterNonUnique(int[] elements) {
    return Arrays.stream(elements)
            .filter(el -> indexOf(elements, el) == lastIndexOf(elements, el))
            .toArray();
}


⬆ 回到顶部

flatten

使数组扁平。

使用 Arrays.stream().flatMapToInt().toArray() 创建一个新数组。

public static int[] flatten(Object[] elements) {
    return Arrays.stream(elements)
            .flatMapToInt(el -> el instanceof int[]
                    ? Arrays.stream((int[]) el)
                    : IntStream.of((int) el)
            ).toArray();
}


⬆ 回到顶部

flattenDepth

将数组压平到指定的深度。

public static Object[] flattenDepth(Object[] elements, int depth) {
    if (depth == 0) {
        return elements;
    }
    return Arrays.stream(elements)
            .flatMap(el -> el instanceof Object[]
                    ? Arrays.stream(flattenDepth((Object[]) el, depth - 1))
                    : Arrays.stream(new Object[]{el})
            ).toArray();


}


⬆ 回到顶部

groupBy

根据给定函数对数组元素进行分组。

使用 Arrays.stream().collect(Collectors.groupingBy()) 分组。

public static <T, R> Map<R, List<T>> groupBy(T[] elements, Function<T, R> func) {
    return Arrays.stream(elements).collect(Collectors.groupingBy(func));
}


⬆ 回到顶部

initial

返回数组中除去最后一个的所有元素。

使用 Arrays.copyOfRange() 返回除最后一个之外的所有元素。

public static <T> T[] initial(T[] elements) {
    return Arrays.copyOfRange(elements, 0, elements.length - 1);
}


⬆ 回到顶部

initializeArrayWithRange

初始化一个数组,该数组包含在指定范围内的数字,传入 startend

public static int[] initializeArrayWithRange(int end, int start) {
    return IntStream.rangeClosed(start, end).toArray();
}


⬆ 回到顶部

initializeArrayWithValues

使用指定的值初始化并填充数组。

public static int[] initializeArrayWithValues(int n, int value) {
    return IntStream.generate(() -> value).limit(n).toArray();
}


⬆ 回到顶部

intersection

返回两个数组中存在的元素列表。

从第二步创建一个集合,然后在 a 上使用 Arrays.stream().filter() 来保存包含在 b 中的值。

public static int[] intersection(int[] first, int[] second) {
    Set<Integer> set = Arrays.stream(second).boxed().collect(Collectors.toSet());
    return Arrays.stream(first)
            .filter(set::contains)
            .toArray();
}


⬆ 回到顶部

isSorted

如果数组按升序排序,则返回 1,如果数组按降序排序,返回 -1,如果没有排序,则返回 0

计算前两个元素的排序 direction。使用for循环对数组进行迭代,并对它们进行成对比较。如果 direction 发生变化,则返回 0, 如果到达最后一个元素,则返回 direction

public static <T extends Comparable<? super T>> int isSorted(T[] arr) {
    final int direction = arr[0].compareTo(arr[1]) < 0 ? 1 : -1;
    for (int i = 0; i < arr.length; i++) {
        T val = arr[i];
        if (i == arr.length - 1) return direction;
        else if ((val.compareTo(arr[i + 1]) * direction > 0)) return 0;
    }
    return direction;
}


⬆ 回到顶部

join

将数组的所有元素连接到字符串中,并返回此字符串。

使用 IntStream.range 创建一个指定索引的数组。然后,使用 Stream.reduce 将元素组合成字符串。

public static <T> String join(T[] arr, String separator, String end) {
    return IntStream.range(0, arr.length)
            .mapToObj(i -> new SimpleEntry<>(i, arr[i]))
            .reduce("", (acc, val) -> val.getKey() == arr.length - 2
                    ? acc + val.getValue() + end
                    : val.getKey() == arr.length - 1 ? acc + val.getValue() : acc + val.getValue() + separator, (fst, snd) -> fst);
}


⬆ 回到顶部

nthElement

返回数组的第n个元素。

Use Arrays.copyOfRange() 优先得到包含第n个元素的数组。

public static <T> T nthElement(T[] arr, int n) {
    if (n > 0) {
        return Arrays.copyOfRange(arr, n, arr.length)[0];
    }
    return Arrays.copyOfRange(arr, arr.length + n, arr.length)[0];
}


⬆ 回到顶部

pick

从对象中选择与给定键对应的键值对。

使用 Arrays.stream 过滤 arr 中存在的所有键。然后,使用 Collectors.toMap 将所有的key转换为Map。

public static <T, R> Map<T, R> pick(Map<T, R> obj, T[] arr) {
    return Arrays.stream(arr)
            .filter(obj::containsKey)
            .collect(Collectors.toMap(k -> k, obj::get));
}


⬆ 回到顶部

reducedFilter

根据条件筛选对象数组,同时筛选出未指定的键。

使用 Arrays.stream().filter() 根据谓词 fn 过滤数组,以便返回条件为真的对象。 对于每个过滤的Map对象,创建一个新的Map,其中包含 keys 中的键。最后,将Map对象收集到一个数组中。

public static Map<String, Object>[] reducedFilter(Map<String, Object>[] data, String[] keys, Predicate<Map<String, Object>> fn) {
    return Arrays.stream(data)
            .filter(fn)
            .map(el -> Arrays.stream(keys).filter(el::containsKey)
                    .collect(Collectors.toMap(Function.identity(), el::get)))
            .toArray((IntFunction<Map<String, Object>[]>) Map[]::new);
}


⬆ 回到顶部

sample

从数组中返回一个随机元素。

使用 Math.Randoman() 生成一个随机数,然后将它乘以数组的 length,然后使用 Math.floor() 获得一个最近的整数,该方法也适用于字符串。

public static <T> T sample(T[] arr) {
    return arr[(int) Math.floor(Math.random() * arr.length)];
}


⬆ 回到顶部

sampleSize

arrayarray 大小的唯一键获取 n 个随机元素。

根据Fisher-Yates算法,使用 Array.copyOfRange() 获得优先的 n 个元素。

public static <T> T[] sampleSize(T[] input, int n) {
    T[] arr = Arrays.copyOf(input, input.length);
    int length = arr.length;
    int m = length;
    while (m > 0) {
        int i = (int) Math.floor(Math.random() * m--);
        T tmp = arr[i];
        arr[i] = arr[m];
        arr[m] = tmp;
    }
    return Arrays.copyOfRange(arr, 0, n > length ? length : n);
}


⬆ 回到顶部

shuffle

将数组值的顺序随机化,返回一个新数组。

根据 Fisher-Yates 算法 重新排序数组的元素。

public static <T> T[] shuffle(T[] input) {
    T[] arr = Arrays.copyOf(input, input.length);
    int length = arr.length;
    int m = length;
    while (m > 0) {
        int i = (int) Math.floor(Math.random() * m--);
        T tmp = arr[i];
        arr[i] = arr[m];
        arr[m] = tmp;
    }
    return arr;
}


⬆ 回到顶部

similarity

返回出现在两个数组中的元素数组。

使用 Arrays.stream().filter() 移除,然后使用 Arrays.stream().anyMatch() 匹配 second 部分的值。

public static <T> T[] similarity(T[] first, T[] second) {
    return Arrays.stream(first)
            .filter(a -> Arrays.stream(second).anyMatch(b -> Objects.equals(a, b)))
            // Make a new array of first's runtime type, but empty content:
            .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass()));
}


⬆ 回到顶部

sortedIndex

返回值应该插入到数组中的最低索引,以保持其排序顺序。

检查数组是否按降序(松散地)排序。 使用 IntStream.range().filter() 来找到元素应该被插入的合适的索引。

public static <T extends Comparable<? super T>> int sortedIndex(T[] arr, T el) {
    boolean isDescending = arr[0].compareTo(arr[arr.length - 1]) > 0;
    return IntStream.range(0, arr.length)
            .filter(i -> isDescending ? el.compareTo(arr[i]) >= 0 : el.compareTo(arr[i]) <= 0)
            .findFirst()
            .orElse(arr.length);
}


⬆ 回到顶部

symmetricDifference

返回两个数组之间的对称差异。

从每个数组中创建一个 Set,然后使用 Arrays.stream().filter() 来保持其他值不包含的值。最后,连接两个数组并创建一个新数组并返回。

public static <T> T[] symmetricDifference(T[] first, T[] second) {
    Set<T> sA = new HashSet<>(Arrays.asList(first));
    Set<T> sB = new HashSet<>(Arrays.asList(second));

    return Stream.concat(
            Arrays.stream(first).filter(a -> !sB.contains(a)),
            Arrays.stream(second).filter(b -> !sA.contains(b))
    ).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass()));
}


⬆ 回到顶部

tail

返回数组中除第一个元素外的所有元素。

如果数组的长度大于1,则返回 Arrays.copyOfRange(1),否则返回整个数组。

public static <T> T[] tail(T[] arr) {
    return arr.length > 1
            ? Arrays.copyOfRange(arr, 1, arr.length)
            : arr;
}


⬆ 回到顶部

take

返回一个从开头删除n个元素的数组。

public static <T> T[] take(T[] arr, int n) {
    return Arrays.copyOfRange(arr, 0, n);
}


⬆ 回到顶部

takeRight

返回从末尾移除n个元素的数组。

使用 Arrays.copyOfRange() 用从末尾取来的 N 个元素来创建一个数组。

public static <T> T[] takeRight(T[] arr, int n) {
    return Arrays.copyOfRange(arr, arr.length - n, arr.length);
}


⬆ 回到顶部

union

返回两个数组中任何一个中存在的每个元素一次。

使用 ab 的所有值创建一个 Set,并将其转换为数组。

public static <T> T[] union(T[] first, T[] second) {
    Set<T> set = new HashSet<>(Arrays.asList(first));
    set.addAll(Arrays.asList(second));
    return set.toArray((T[]) Arrays.copyOf(new Object[0], 0, first.getClass()));
}


⬆ 回到顶部

without

筛选出具有指定值之一的数组的元素。

使用 Arrays.strean().filter() 创建一个数组,排除(使用 !Arrays.asList(elements).contains())所有命中的值。

public static <T> T[] without(T[] arr, T... elements) {
    List<T> excludeElements = Arrays.asList(elements);
    return Arrays.stream(arr)
            .filter(el -> !excludeElements.contains(el))
            .toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, arr.getClass()));
}


⬆ 回到顶部

zip

根据原始数组中的位置创建元素数组。

public static List<Object[]> zip(Object[]... arrays) {
    OptionalInt max = Arrays.stream(arrays).mapToInt(arr -> arr.length).max();
    return IntStream.range(0, max.getAsInt())
            .mapToObj(i -> Arrays.stream(arrays)
                    .map(arr -> i < arr.length ? arr[i] : null)
                    .toArray())
            .collect(Collectors.toList());
}


⬆ 回到顶部

zipObject

给定有效的属性标识符数组和值数组,返回将属性与值关联的对象。

public static Map<String, Object> zipObject(String[] props, Object[] values) {
    return IntStream.range(0, props.length)
            .mapToObj(i -> new SimpleEntry<>(props[i], i < values.length ? values[i] : null))
            .collect(
                    HashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), HashMap::putAll);
}


⬆ 回到顶部

Maths

average

返回两个或两个以上数字的平均值。

public static double average(int[] arr) {
    return IntStream.of(arr)
            .average()
            .orElseThrow(() -> new IllegalArgumentException("Array is empty"));
}


⬆ 回到顶部

gcd

计算一系列数字的最大公约数(gcd)。

使用 Arrays.stream().reduce() 和 GCD(使用递归公式)计算一组数字的最大公约数。

public static OptionalInt gcd(int[] numbers) {
    return Arrays.stream(numbers)
            .reduce((a, b) -> gcd(a, b));
}

private static int gcd(int a, int b) {
    if (b == 0) {
        return a;
    }
    return gcd(b, a % b);
}


⬆ 回到顶部

lcm

计算数字数组的最低公共倍数(LCM)。

使用 Arrays.stream().reduce() 和 LCM公式(使用递归)来计算数字数组的最低公共倍数。

public static OptionalInt lcm(int[] numbers) {
    IntBinaryOperator lcm = (x, y) -> (x * y) / gcd(x, y);
    return Arrays.stream(numbers)
            .reduce((a, b) -> lcm.applyAsInt(a, b));
}

private static int gcd(int a, int b) {
    if (b == 0) {
        return a;
    }
    return gcd(b, a % b);
}


⬆ 回到顶部

findNextPositivePowerOfTwo

查找大于或等于该值的下一个幂。

该方法使用左移运算符将1与右侧的值位移。右侧使用 Integer.numberOfLeadingZeros方法。 001 << 2 would be 100. 100 in decimal is equal to 4.

Integer.numberOfLeadingZeros 给出了数值前导零的数目。例如,调用 Integer.numberOfLeadingZeros(3) 将赋值为30。 这是因为3在二进制中表示为 11。由于整数有32位,所以有30位有0位。左移运算符的右边变为 32-30 = 2。 左移1,即 001 << 2 将是 100,十进制中的 100 等于 4

public static int findNextPositivePowerOfTwo(int value) {
    return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));
}


⬆ 回到顶部

isEven

检查数字是否是偶数。

这个方法使用按位运算符,0b1 是1的二进制表示。 因为Java 7可以通过用 0b0B 作为前缀来编写二进制文字。 数字为偶数时, 运算符将返回0。 例如,IsEven(4) 会导致 100 & 001 的结果将是 000

public static boolean isEven(final int value) {
    return (value & 0b1) == 0;
}


⬆ 回到顶部

isPowerOfTwo

检查一个值是2的正幂。

为了理解它是如何工作的,让我们假设我们调用了 IsPowerOfTwo(4)

当值大于0时,将评估 && 运算符的右侧。

(~value + 1) 的结果等于值本身,~100 + 001 => 011 + 001 => 100

(value & value) 的结果是value,100 & 100 => 100.。

当值等于值时,这将把值表达为真值。

public static boolean isPowerOfTwo(final int value) {
    return value > 0 && ((value & (~value + 1)) == value);
}


⬆ 回到顶部

generateRandomInt

生成一个介于 Integer.MIN_VALUEInteger.MAX_VALUE 之间的随机数。

public static int generateRandomInt() {
    return ThreadLocalRandom.current().nextInt();
}


⬆ 回到顶部

String

anagrams

生成一个字符串的所有字符(包含重复)。

public static List<String> anagrams(String input) {
    if (input.length() <= 2) {
        return input.length() == 2
                ? Arrays.asList(input, input.substring(1) + input.substring(0, 1))
                : Collections.singletonList(input);
    }
    return IntStream.range(0, input.length())
            .mapToObj(i -> new SimpleEntry<>(i, input.substring(i, i + 1)))
            .flatMap(entry ->
                    anagrams(input.substring(0, entry.getKey()) + input.substring(entry.getKey() + 1))
                            .stream()
                            .map(s -> entry.getValue() + s))
            .collect(Collectors.toList());
}


⬆ 回到顶部

byteSize

以字节为单位返回字符串的长度。

public static int byteSize(String input) {
    return input.getBytes().length;
}


⬆ 回到顶部

capitalize

将字符串首字母大写。

public static String capitalize(String input, boolean lowerRest) {
    return input.substring(0, 1).toUpperCase() +
            (lowerRest
                    ? input.substring(1, input.length()).toLowerCase()
                    : input.substring(1, input.length()));
}


⬆ 回到顶部

capitalizeEveryWord

将字符串中每个单词的首字母大写。

public static String capitalizeEveryWord(final String input) {
    return Pattern.compile("\\b(?=\\w)").splitAsStream(input)
            .map(w -> capitalize(w, false))
            .collect(Collectors.joining());
}


⬆ 回到顶部

countVowels

在提供的字符串中返回元音的个数。

public static int countVowels(String input) {
    return input.replaceAll("[^aeiouAEIOU]", "").length();
}


⬆ 回到顶部

escapeRegExp

转义要在正则表达式中使用的字符串。

public static String escapeRegExp(String input) {
    return Pattern.quote(input);
}


⬆ 回到顶部

fromCamelCase

从驼峰式转换字符串。

public static String fromCamelCase(String input, String separator) {
    return input
            .replaceAll("([a-z\\d])([A-Z])", "$1" + separator + "$2")
            .toLowerCase();
}


⬆ 回到顶部

isAbsoluteUrl

如果给定的字符串是绝对URL,则返回 true,否则返回 false

public static boolean isAbsoluteUrl(String url) {
    return Pattern.compile("^[a-z][a-z0-9+.-]*:").matcher(url).find();
}


⬆ 回到顶部

isLowerCase

检查字符串是否为小写。

public static boolean isLowerCase(String input) {
    return Objects.equals(input, input.toLowerCase());
}


⬆ 回到顶部

isUpperCase

检查字符串是否为大写。

public static boolean isUpperCase(String input) {
    return Objects.equals(input, input.toUpperCase());
}


⬆ 回到顶部

isPalindrome

判断一个字符串是否回文。

public static boolean isPalindrome(String input) {
    String s = input.toLowerCase().replaceAll("[\\W_]", "");
    return Objects.equals(
            s,
            new StringBuilder(s).reverse().toString()
    );
}


⬆ 回到顶部

isNumeric

检查字符串是否为数字。

public static boolean isNumeric(final String input) {
    return IntStream.range(0, input.length())
            .allMatch(i -> Character.isDigit(input.charAt(i)));
}


⬆ 回到顶部

mask

用指定的掩码字符替换除最后 num 个字符以外的所有字符。

public static String mask(String input, int num, String mask) {
    int length = input.length();
    return num > 0
            ?
            input.substring(0, length - num).replaceAll(".", mask)
                    + input.substring(length - num)
            :
            input.substring(0, Math.negateExact(num))
                    + input.substring(Math.negateExact(num), length).replaceAll(".", mask);
}


⬆ 回到顶部

reverseString

反转字符串。

public static String reverseString(String input) {
    return new StringBuilder(input).reverse().toString();
}


⬆ 回到顶部

sortCharactersInString

按字母顺序排列字符串中的字符。

public static String sortCharactersInString(String input) {
    return Arrays.stream(input.split("")).sorted().collect(Collectors.joining());
}


⬆ 回到顶部

splitLines

将多行字符串拆分为行数组。

public static String[] splitLines(String input) {
    return input.split("\\r?\\n");
}


⬆ 回到顶部

toCamelCase

转换一个字符串为驼峰式。

public static String toCamelCase(String input) {
    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);
    List<String> matchedParts = new ArrayList<>();
    while (matcher.find()) {
        matchedParts.add(matcher.group(0));
    }
    String s = matchedParts.stream()
            .map(x -> x.substring(0, 1).toUpperCase() + x.substring(1).toLowerCase())
            .collect(Collectors.joining());
    return s.substring(0, 1).toLowerCase() + s.substring(1);
}


⬆ 回到顶部

toKebabCase

将字符串转换为kebab大小写。

public static String toKebabCase(String input) {
    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);
    List<String> matchedParts = new ArrayList<>();
    while (matcher.find()) {
        matchedParts.add(matcher.group(0));
    }
    return matchedParts.stream()
            .map(String::toLowerCase)
            .collect(Collectors.joining("-"));
}


⬆ 回到顶部

match

正则匹配。

public static List<String> match(String input, String regex) {
    Matcher matcher = Pattern.compile(regex).matcher(input);
    List<String> matchedParts = new ArrayList<>();
    while (matcher.find()) {
        matchedParts.add(matcher.group(0));
    }
    return matchedParts;
}


⬆ 回到顶部

toSnakeCase

将字符串转换为蛇形小写,如 Im_Biezhi

public static String toSnakeCase(String input) {
    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);
    List<String> matchedParts = new ArrayList<>();
    while (matcher.find()) {
        matchedParts.add(matcher.group(0));
    }
    return matchedParts.stream()
            .map(String::toLowerCase)
            .collect(Collectors.joining("_"));
}


⬆ 回到顶部

truncateString

将字符串截断到指定的长度。

public static String truncateString(String input, int num) {
    return input.length() > num
            ? input.substring(0, num > 3 ? num - 3 : num) + "..."
            : input;
}


⬆ 回到顶部

words

将给定的字符串转换为单词数组。

public static String[] words(String input) {
    return Arrays.stream(input.split("[^a-zA-Z-]+"))
            .filter(s -> !s.isEmpty())
            .toArray(String[]::new);
}


⬆ 回到顶部

stringToIntegers

将由空格分隔的数字字符串转换为 int 数组。

public static int[] stringToIntegers(String numbers) {
        return Arrays.stream(numbers.split(" ")).mapToInt(Integer::parseInt).toArray();
}


⬆ 回到顶部

IO

convertInputStreamToString

将InputStream转换为字符串。

public static String convertInputStreamToString(final InputStream in) throws IOException {
    ByteArrayOutputStream result = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length;
    while ((length = in.read(buffer)) != -1) {
        result.write(buffer, 0, length);
    }
    return result.toString(StandardCharsets.UTF_8.name());
}


⬆ 回到顶部

readFileAsString

将文件内容读入字符串。

public String readFileAsString(Path path) throws IOException {
    return new String(Files.readAllBytes(path));
}


⬆ 回到顶部

getCurrentWorkingDirectoryPath

获取当前工作目录。

public static String getCurrentWorkingDirectoryPath() {
    return FileSystems.getDefault().getPath("").toAbsolutePath().toString();
}


⬆ 回到顶部

tmpDirName

返回 java.io.tmpdir 系统属性的值。如果末尾没有分隔符,则追加分隔符。

public static String tmpDirName() {
    String tmpDirName = System.getProperty("java.io.tmpdir");
    if (!tmpDirName.endsWith(File.separator)) {
        tmpDirName += File.separator;
    }

    return tmpDirName;
}


⬆ 回到顶部

Exception

stackTraceAsString

将异常堆栈跟踪转换为字符串。

public static String stackTraceAsString(final Throwable throwable) {
    final StringWriter sw = new StringWriter();
    throwable.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}


⬆ 回到顶部

System

osName

以小写字符串的形式获取操作系统的名称。

public static String osName() {
    return System.getProperty("os.name").toLowerCase();
}


⬆ 回到顶部

isDebuggerEnabled

检查JVM是否为debug模式。

public static boolean isDebuggerAttached() {
    final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    return runtimeMXBean.getInputArguments()
            .stream()
            .anyMatch(arg -> arg.contains("-agentlib:jdwp"));

}


⬆ 回到顶部

Class

getAllInterfaces

此方法返回由给定类及其超类实现的所有接口。

该方法通过连接两个Stream来工作。第一个Stream是通过创建带有接口的流和接口实现的所有接口来递归构建的。 第二个Stream对超类也是如此。其结果是删除重复项后将两个Stream连接起来。

public static List<Class<?>> getAllInterfaces(Class<?> cls) {
    return Stream.concat(
            Arrays.stream(cls.getInterfaces()).flatMap(intf ->
                    Stream.concat(Stream.of(intf), getAllInterfaces(intf).stream())),
            cls.getSuperclass() == null ? Stream.empty() : getAllInterfaces(cls.getSuperclass()).stream()
    ).distinct().collect(Collectors.toList());
}


⬆ 回到顶部

isInnerClass

此方法检查指定的类是内部类还是静态嵌套类。

public static boolean isInnerClass(final Class<?> cls) {
    return cls != null && cls.getEnclosingClass() != null;
}


⬆ 回到顶部

Enum

getEnumMap

将枚举转换为 Map,其中 key 是枚举名,value 是枚举本身。

public static <E extends Enum<E>> Map<String, E> getEnumMap(final Class<E> enumClass) {
    return Arrays.stream(enumClass.getEnumConstants())
            .collect(Collectors.toMap(Enum::name, Function.identity()));
}


⬆ 回到顶部

CC0 1.0 Universal Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. For more information, please see <http://creativecommons.org/publicdomain/zero/1.0/>

简介

30 seconds to collect useful Java8 snippet 展开 收起
Java
CC0-1.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/angcyo/30-seconds-of-java8.git
git@gitee.com:angcyo/30-seconds-of-java8.git
angcyo
30-seconds-of-java8
30-seconds-of-java8
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891