preface

Although stream was introduced in Java8, most people don’t use this very useful feature. This article gives you an idea of some of the benefits of using stream to make code more concise and readable. This article requires a basic understanding of lambda syntax and the basic concepts and methods of stream creation. For basic concepts and methods of stream creation, see my article.

skills

  • Array run set

    If you are a regular reader of LeetCode, you will occasionally encounter a situation where you need to interconvert a List with an array of primitive types, and then you will need to write code like this:

    // Store the List elements in an array
    List<Integer> list = new ArrayList<>(Arrays.asList(1.2.3.4.5));
    int[] arr = new int[list.size()];
    Integer[] temp = list.toArray(new Integer[0]);
    for (int i = 0; i < temp.length; i++) {
    	arr[i] = temp[i];
    }
    
    // Store the array elements in the List
    int[] arr = {1.2.3.4.5};
    List<Integer> list = new ArrayList<>();
    for (int val : arr) {
    	list.add(val);
    }
    Copy the code

    The above two transformations are easy to write, but the need to write a loop each time, and the need to use a temporary array when converting an array to a List, can be very uncomfortable. However, if you use stream, the same function can be implemented as follows:

    // Store the List elements in an array
    List<Integer> list = new ArrayList<>(Arrays.asList(1.2.3.4.5));
    int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
    
    // Store the array elements in the List
    int[] arr = {1.2.3.4.5};
    List<Integer> list = IntStream.of(arr).boxed().collect(Collectors.toList());
    Copy the code

    We can see that by using Stream, we can write more coherent code, make the code more reliable and maintainable, and focus on business functions. Even if you are not familiar with lambda syntax, you will be able to read the above code easily.

  • Count the number of elements in an array

    Suppose we now need to count and print the number of occurrences of each element and its corresponding element in an array with repeated elements. As you can imagine, we can easily solve this problem using a Map, as follows:

    String[] arr = {"a"."c"."a"."b"."d"."c"};
    Map<String, Integer> map = new HashMap<>();
    for (String s : arr) {
        if (map.containsKey(s)) {
            map.put(s, map.get(s) + 1);
        } else {
            map.put(s, 1);
        }
    }
    map.forEach((key, value) -> System.out.println(key + ":" + value));
    Copy the code

    If you are more familiar with the API in Map, you might write a more concise code like this:

    String[] arr = {"a"."c"."a"."b"."d"."c"};
    Map<String, Integer> map = new HashMap<>();
    for (String s : arr) {
        map.put(s, map.getOrDefault(s, 0) + 1);
    }
    map.forEach((key, value) -> System.out.println(key + ":" + value));
    Copy the code

    However, if we use stream, we can also write much cleaner code, again without the annoying loop, and with only two lines of code (newline for readability) :

    String[] arr = {"a"."c"."a"."b"."d"."c"};
    Stream.of(arr)
          .collect(Collectors.toMap(k -> k, k -> 1, Integer::sum))
          .forEach((k, v) -> System.out.println(k + ":" + v));
    Copy the code

    Pay attention to

    Collectors. ToMap (k -> k, k -> 1, Integer::sum) may be difficult to understand. The first parameter indicates that each element in the ARR is the key in the Map. The second parameter represents the value of each key, where each element has a number of 1. The third parameter represents how to merge elements with the same key. Integer::sum is used to add the values of elements with the same key. This enables a count of the number of elements per element.

  • A custom sort of array of basic data types

    Sometimes we will encounter custom sort an array of basic data types, different packaging types of arrays and collections can be used directly comparator, we can only through the basic type of an array type array into packaging or stored in the collection, in order to after the completion of the basic types of arrays, moreover, we can only write a sorting algorithm, Modify the sorting algorithm in comparison to achieve. Either way, we can’t focus on the logic and have to write some extra code, or even modify the underlying logic, like this:

    int[] arr = {1.5.9.7.2.3.7, -1.0.3};
    // Convert the array to wrapper type for custom sorting
    Integer[] temp = new Integer[arr.length];
    for (int i = 0; i < arr.length; i++) {
        temp[i] = arr[i];
    }
    Arrays.sort(temp, Comparator.reverseOrder());
    for (int i = 0; i < temp.length; i++) {
        arr[i] = temp[i];
    }
    
    // Convert the array to a collection type for a custom sort
    List<Integer> list = new ArrayList<>();
    for (int val : arr) {
        list.add(val);
    }
    list.sort(Collections.reverseOrder());
    for (int i = 0; i < list.size(); i++) {
        arr[i] = list.get(i);
    }
    
    // Compare rules by handwriting sorting algorithm
    // To make the code more concise, the most violent and unoptimized bubble sort is used
    int[] arr = {1.5.9.7.2.3.7, -1.0.3};
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] < arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp; }}}Copy the code

    The above several ways can be found, we all need to write a lot of code, unable to focus on the design custom sorting this issue, but through the use of the stream, we can write the following concise code (if you want, you can also write a series of chain operation in one line, but for the sake of the readability of the code, it is not recommended to do so) :

    int[] arr = {1.5.9.7.2.3.7, -1.0.3};
    arr = IntStream.of(arr)
                   .boxed()
                   .sorted(Comparator.reverseOrder())
                   .mapToInt(Integer::intValue)
                   .toArray();
    Copy the code

    Pay attention to

    All we need to do is call the sort method of Arrays and invert the array elements. But for custom sorting, it’s not going to be as simple as inverting Arrays in most cases, so I wrote some more generic code.

  • Count the first k high-frequency elements in the array

    In the end, we practice through a problem in order to better experience the power of the stream, when we in practice the problem, of course, more need to be consider from the Angle of the algorithm the solution to the problem, but in this article, we mainly in order to explain the use of the stream, so the things I won’t go to consider algorithm, click here to see the original link, With stream, we could write something as simple as the following:

    class Solution {
        public int[] topKFrequent(int[] nums, int k) {
            return Arrays.stream(nums)
                         .boxed()
                         .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)) .entrySet() .stream() .sorted((m1, m2) -> m2.getValue() - m1.getValue()) .limit(k) .mapToInt(Map.Entry::getKey) .toArray(); }}Copy the code

conclusion

This article introduces a few simple and practical techniques for using stream. Of course, there is more to stream than that. I hope this article will stimulate your interest in learning about stream.