Syntax for Lambda expressions

Basic syntax:

(parameters) -> expression
或
(parameters) ->{ statements; }
Copy the code

Method references

Method references are represented by a pair of double colons ::. Method references are another way of writing a functional interface

  1. Static method reference, by class name :: Static method name, such as Integer::parseInt
  2. Instance methods are referenced by instance object :: instance methods, such as STR ::substring
  3. You can also use the class name :: instance method name, such as String:: SubString
  4. Constructor method references through the class name ::new, such as User::new

Third point: If the first argument in the Lambda argument list is the caller of the instance method and the second argument (or no argument) is the argument of the instance method, the format is class name :: instance method name

There are several basic function shapes,

including Function (unary function from T to R), Consumer (unary function from T to void), Predicate (unary function from T to boolean), and Supplier (nullary function to R).

Function shapes have a natural arity based on how they are most commonly used. The basic shapes can be modified by an arity prefix to indicate a different arity, such as BiFunction (binary function from T and U to R).

Class name :: Method name, equivalent to a reference to this method closure, similar to a function in JS. Such as:

public static void main(String[] args) {
        Consumer<String> printStrConsumer = DoubleColon::printStr;
        printStrConsumer.accept("printStrConsumer");
         
        Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;
        toUpperConsumer.accept(new DoubleColon());
         
        BiConsumer<DoubleColon,String> toLowerConsumer = DoubleColon::toLower;
        toLowerConsumer.accept(new DoubleColon(),"toLowerConsumer");
         
        BiFunction<DoubleColon,String,Integer> toIntFunction = DoubleColon::toInt;
        int i = toIntFunction.apply(new DoubleColon(),"toInt");
    }

	static class DoubleColon {
		 
	    public static void printStr(String str) {
	        System.out.println("printStr : " + str);
	    }
	 
	    public void toUpper(a){
	        System.out.println("toUpper : " + this.toString());
	    }
	 
	    public void toLower(String str){
	        System.out.println("toLower : " + str);
	    }
	 
	    public int toInt(String str){
	        System.out.println("toInt : " + str);
	        return 1; }}Copy the code

The main difference between static and non-static methods is that the non-static method has one more parameter than the static method, which is the instance to be called.

// Use double colons :: to construct non-static function references
	    String content = "Hello JDK8";
	    
	    // public String substring(int beginIndex)
	    Object :: non-static method
	    Function<Integer, String> func = content::substring;
	    String result = func.apply(1);
	    System.out.println(result);
	    
	    //
	    IntFunction<String> intFunc = content::substring;
	    result = intFunc.apply(1);
	    System.out.println(result);
	    
	    String:: non-static method
	    BiFunction<String,Integer,String> lala = String::substring;
	    String s = lala.apply(content, 1);
	    System.out.println(s);
	    
	    // public String toUpperCase()
	    // A function reference is also a functional interface, so you can also use a function reference as an argument to a method
	    Function<String, String> func2 = String::toUpperCase;
	    result = func2.apply("lalala");
	    System.out.println(result);
	    
	    Supplier: void (" Supplier ") returns String
	    Supplier<String> supplier = "alalal"::toUpperCase;
	    result = supplier.get();
	    System.out.println(result);
Copy the code

An array reference

        // Traditional Lambda implementations
        IntFunction<int[]> function = (i) -> new int[i];
        int[] apply = function.apply(5);
        System.out.println(apply.length); / / 5

        // Array type reference implementation
        function = int[] : :new;
        apply = function.apply(10);
        System.out.println(apply.length); / / 10
Copy the code

The use of the Optional

c static void main(String[] args) {
    // The Optional class is already part of the Java 8 library. It has been in Guava for a long time
    // Optional resolves NullPointerException exceptions to make code more strict
    String msg = "hello";
    Optional<String> optional = Optional.of(msg);
    // Check whether there is a value, not null
    boolean present = optional.isPresent();
    // Return the value if there is a value, throw an exception if it is null
    String value = optional.get();
    // If null, return the value specified else
    String hi = optional.orElse("hi");
    // If the value is not empty, the Lambda expression is executed
    optional.ifPresent(opt -> System.out.println(opt));
Copy the code

Some operations on Stream

Some streams can be turned into collections, such as toList, which generates instances of the java.util.List class. Of course, there are toSet and toCollection, which generate instances of the Set and Collection classes, respectively.

final List<String> list = Arrays.asList("jack"."mary"."lucy");
		
		// Filter + output
		System.out.println("Filter + output:"); Stream<String> stream = list.stream(); stream.filter(item -> ! item.equals("zhangsan")) .filter(item -> ! item.equals("wangwu"))
			.forEach(item -> System.out.println(item));
		
		// Limit to 2
		System.out.println("limit(2): ");
		list.stream().limit(2).forEach(System.out::println);
		
		/ / sorting
		System.out.println("Sort:");
		list.stream().sorted((o1, o2) -> o1.compareTo(o2)).forEach(System.out::println);
		
		// Fetch the maximum value
		System.out.println("max: ");
		String result = list.stream().max((o1, o2) -> o1.compareTo(o2)).orElse("error");
		System.out.println(result);
		
		
		// toList
		System.out.println("toList: ");
		List<Integer> collectList = Stream.of(1.2.3.4)
		        .collect(Collectors.toList());
		System.out.println("collectList: " + collectList);
		// Print the result
		// collectList: [1, 2, 3, 4]
		
		// toSet
		System.out.println("toSet: ");
		Set<Integer> collectSet = Stream.of(1.2.3.4)
		        .collect(Collectors.toSet());
		System.out.println("collectSet: " + collectSet);
		// Print the result
		// collectSet: [1, 2, 3, 4]
Copy the code

List to Map (via stream)

List<Person> list = new ArrayList<>();
		list.add(new Person(1."mary"));
		list.add(new Person(2."lucy"));
		
		Map<Integer, Person> map = list.stream().collect(Collectors.toMap(Person::getId, Function.identity()));
		System.out.println(map);
		{1=Main3$Person@42f30e0a, 2=Main3$Person@24273305}
		
		Map<Integer, String> map2 = list.stream().collect(Collectors.toMap(Person::getId, Person::getName)); 
		System.out.println(map2);
		{1= Mary, 2= Lucy}
Copy the code

Split data block

Map<Boolean, List<Integer>> map = Stream.of(1.2.3.4)
	        .collect(Collectors.partitioningBy(item -> item > 2));
		System.out.println(map);

// Output: {false=[1, 2], true=[3, 4]}
Copy the code

The return value of a function can only be divided into two sets of data: true and false.

Block grouping

Grouping data is a more natural way to split data. Instead of dividing data into true and false parts, you can group data with arbitrary values.

GroupingBy groups all sets. The result is in the form of Map

. Key is the type of the field to be grouped. For example, the type of the field to be grouped is Integer and the key type of the Map to be grouped is Integer. The result is Map

. Suppose we want a set of user type 1, first group it, as in: Map

> userMap = allUserList.parallelStream().collect(Collectors.groupingBy(User::getType)); List

userList = usermap.get (1);

,list
,list>
,list>

Pit between groupingBy and partitioningBy

1. It is important to note that when performing get, the groupingBy group returns null if the key does not exist. The partitioningBy group returns an empty array.

2. Stream processing collections is not necessarily more efficient than iterators, and parallelStream can be used to process parallel streams if ordering is not required.

string

In Java 1.8, we can do this using Stream. Here we will collect the values in the Stream using Collectors. Joining, which is a convenient way to get the Stream to a string. The joining function takes three arguments, allowing (to separate elements), a prefix, and a suffix.

String strJoin = Stream.of("1"."2"."3"."4")
        .collect(Collectors.joining(","."["."]"));
System.out.println("strJoin: " + strJoin);
// Print the result
/ / strJoin: [1, 2, 3, 4]
Copy the code

TODO reading + understanding: Java8 used in stream grouping statistics and general implementation of the performance of the packet statistics contrast _ Feng Libin blog – CSDN _java stream packet statistics blog.csdn.net/fenglibing/…

reference

JDK1.8 new features (3) : method reference: : and Optional blog.csdn.net/vbirdbest/a…

Blog.csdn.net/IO_Field/ar… The basic syntax of Java 8 series Stream is explained in detail

Blog.csdn.net/V_Axis/arti…