Lambda expressions
A lambda expression is an anonymous function, that is, a function without a function name
For example, we usually create threads
/ / Runnable implementation class
public class RunnableImpl implements Runnable {
@Override
public void run(a) {
logger.info("The Runnable implementation class creates and starts a new thread"); }}// Create and start a thread using the traditional Runnable object
new Thread(new RunnableImpl()).start();
// Create and start a thread using an anonymous inner class
new Thread(new Runnable() {
@Override
public void run(a) {
logger.info("Create and start a new thread using an anonymous inner class.");
}
}).start();
// Simplify anonymous inner classes as lambda expressions
new Thread(()-> logger.info("Lambda expression creates and starts a new thread")).start();
Copy the code
Advantages: Lambda expressions have cleaner code than the traditional way of creating a Thread by passing a Runnable object as an argument to the Thread class
Method references
Method references encapsulate a method as a variable. :: Double colons are symbols for method references
// method reference that converts the string 100 to an Integer type
Function<String, Integer> function = Integer::parseInt;
Integer IntegerResult= function.apply("100");
Copy the code
The return value type of a method reference is a functional interface
The parameter number, type, and return value type of the referenced method must be the same as the declaration of the method in the functional interface. As long as this requirement is met, any type of functional interface can be returned
//Function The apply method accepts variables of type T and returns results of type R
@FunctionalInterface
public interface Function<T.R> {
R apply(T t); } Integer.paseint () takes a string parameter and returns a result of type Integer// Compare two int values, either of the following return value types can be used
Comparator<Integer> compare = Integer::compare;
int compare1 = compare.compare(1.2);
IntBinaryOperator compare = Integer::compare;
int compare1 = compare.applyAsInt(1.2);
Copy the code
There are many functional interfaces under the java.util.function package
Customize a functional interface
@functionalInterface public interface KiteFunction<T,R,S> {R run(T T, S S); }Copy the code
Customize a method that corresponds to KiteFunction’s run method team
// The dateFormat method is used to format a date in a specified format. Public class TimeConverse {public static String dateFormat(LocalDateTime,String Pattern){public static String dateFormat(LocalDateTime,String Pattern){ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); String dateStr = localDateTime.format(dateTimeFormatter); return dateStr; }}Copy the code
KiteFunction<LocalDateTime, String, String> dateFormat = TimeConverse::dateFormat;
String dateStr = dateFormat.run(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");
System.out.println(dateStr);
Copy the code
If the dateFormat method of TimeConverse is called only once, we can also implement it directly in the Run method of the kiteFunction interface (similar to how the Runnable interface creates and starts a new thread) as an anonymous inner class
String dateStr2 = new KiteFunction<LocalDateTime, String, String>() {
@Override
public String run(LocalDateTime localDateTime, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return localDateTime.format(dateTimeFormatter);
}
}.run(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");
Copy the code
The anonymous inner class above can be replaced with a lambda expression
String dateStr2 = ((KiteFunction<LocalDateTime, String, String>) (localDateTime, pattern) -> {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return localDateTime.format(dateTimeFormatter);
}).run(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");
Copy the code
The Stream flow
Stream makes extensive use of method references and lambda expressions, as well as a number of easy-to-use packaged utility apis that allow you to quickly and efficiently process complex data
- FlatMap flattens multidimensional data
- Peek is similar to foreach, except that foreach returns no result, while peek returns a Stream. However, if peek is executed without collecting data, no method inside the peek function is executed
- Reduce function to accumulate data
// Reduce method definition
Optional<T> reduce(BinaryOperator<T> accumulator);
// Add the elements in List
Integer result = stream.reduce((x, y) -> x + y).get(); X is the first element in Stream, and y is the second element//reduce overload method definition
T reduce(T identity, BinaryOperator<T> accumulator);
// The actual user assigns an initial value to the summation
stream.reduce(100, (x, y) -> x + y),identity will be the first argumentCopy the code
Common methods of Stream processes
Trader raoul = new Trader("Raoul"."Cambridge");
Trader mario = new Trader("Mario"."Milan");
Trader alan = new Trader("Alan"."Cambridge");
Trader brian = new Trader("Brian"."Cambridge");
List<Transaction> transactions = Arrays.asList(
new Transaction(brian, 2011.300),
new Transaction(raoul, 2012.1000),
new Transaction(raoul, 2011.400),
new Transaction(mario, 2012.710),
new Transaction(mario, 2012.700),
new Transaction(alan, 2012.950));//1. Find all trades in 2011 and sort them in reverse order
List<Transaction> collect = transactions.stream().filter(t -> t.getYear() == 2011).sorted(Comparator.comparing(Transaction::getValue).reversed()).collect(Collectors.toList());
System.out.println(collect);
//2. What different cities have the traders worked in
transactions.stream().map(Transaction::getTrader).map(Trader::getCity).distinct().forEach(e->System.out.println(e));
//3. Determine whether traders have stayed in Milan
boolean isExit = transactions.stream().map(Transaction::getTrader).map(Trader::getCity).anyMatch(e -> "Milan".equals(e));
System.out.println(isExit);
//4. Print all trades of traders living in Cambridge
long sum = transactions.stream().filter(transaction -> "Cambridge".equals(transaction.getTrader().getCity())).collect(Collectors.summarizingInt(Transaction::getValue)).getSum();
System.out.println("Total transaction value in Cambridge."+sum);
//5. Of all the trades, the largest is
Transaction transaction = transactions.stream().max(Comparator.comparing(Transaction::getValue)).get();
System.out.println(transaction);
Copy the code
conclusion
When we talk about functional programming, functions are method references and expressions are Lambda expressions
The Stream Stream can improve our programming efficiency, but it also requires proper use of the StreamAPI and well-written comments when it comes to complex business logic