Java How to Program学习笔记_第十七章_Java SE 8 Lambda及Stream——章节小结(Summary)

第一次正式学习Java的Lambda编程,感觉并不陌生,在Spotfire,PL/SQL, C语言、Excel等很多地方都用过函数式编程。

Summary

Section 17.1 Introduction

• Prior to Java SE 8, Java supported three programming paradigms—procedural programming, object oriented programming and generic programming. Java SE 8 adds functional programming.

• The new language and library capabilities that support functional programming were added to Java as part of Project Lambda.

Section 17.2 Functional Programming Technologies Overview

• Prior to functional programming, you typically determined what you wanted to accomplish, then specified the precise steps to accomplish that task.

• Using a loop to iterate over a collection of elements is known as external iteration and requires accessing the elements sequentially. Such iteration also requires mutable variables.

• In functional programming, you specify what you want to accomplish in a task, but not how to accomplish it.

• Letting the library determine how to iterate over a collection of elements is known as internal iteration. Internal iteration is easier to parallelize.

• Functional programming focuses on immutability —not modifying the data source being processed or any other program state.

Section 17.2.1 Functional Interfaces

• Functional interfaces are also known as single abstract method (SAM) interfaces.

• Package java.util.function contains six basic functional interfaces BinaryOperator, Consumer, Function, Predicate, Supplier and UnaryOperator.

• There are many specialized versions of the six basic functional interfaces for use with int, long and double primitive values. There are also generic customizations of Consumer, Function and Predicate for binary operations—that is, methods that take two arguments.

Section 17.2.2 Lambda Expressions

• A lambda expression represents an anonymous method—a shorthand notation for implementing a functional interface.

• The type of a lambda is the type of the functional interface that the lambda implements.

• Lambda expressions can be used anywhere functional interfaces are expected.

• A lambda consists of a parameter list followed by the arrow token (->) and a body, as in:

(parameterList) -> {statements}

For example, the following lambda receives two ints and returns their sum:

(int x, int y) -> {return x + y;}

This lambda’s body is a statement block that may contain one or more statements enclosed in curly braces.

• A lambda’s parameter types may be omitted, as in:

(x, y) -> {return x + y;}

in which case, the parameter and return types are determined by the lambda’s context.

• A lambda with a one-expression body can be written as:

(x, y) -> x + y

In this case, the expression’s value is implicitly returned.

• When the parameter list contains only one parameter, the parentheses may be omitted, as in:

value -> System.out.printf("%d ", value)

• A lambda with an empty parameter list is defined with () to the left of the arrow token (->), as in:

() -> System.out.println("Welcome to lambdas!")

• There are also specialized shorthand forms of lambdas that are known as method references.

Section 17.2.3 Streams

• Streams are objects that implement interface Stream (from the package java.util.stream) and enable you to perform functional programming tasks. There are also specialized stream interfaces for processing int, long or double values.

• Streams move elements through a sequence of processing steps—known as a stream pipeline— that begins with a data source, performs various intermediate operations on the data source’s elements and ends with a terminal operation. A stream pipeline is formed by chaining method calls.

• Unlike collections, streams do not have their own storage—once a stream is processed, it cannot be reused, because it does not maintain a copy of the original data source.

• An intermediate operation specifies tasks to perform on the stream’s elements and always results in a new stream.

• Intermediate operations are lazy — they aren’t performed until a terminal operation is invoked. This allows library developers to optimize stream-processing performance.

• A terminal operation initiates processing of a stream pipeline’s intermediate operations and produces a result. Terminal operations are eager — they perform the requested operation when they are called.

Section 17.3 IntStream Operations

• An IntStream (package java.util.stream) is a specialized stream for manipulating int values.

Section 17.3.1 Creating an IntStream and Displaying Its Values with the forEach Terminal Operation

IntStream static method of receives an int array as an argument and returns an IntStream for processing the array’s values.

IntStream method forEach (a terminal operation) receives as its argument an object that implements the IntConsumer functional interface (package java.util.function). This interface’s accept method receives one int value and performs a task with it.

• The Java compiler can infer the types of a lambda’s parameters and the type returned by a lambda from the context in which the lambda is used. This is determined by the lambda’s target type

  • the functional interface type that is expected where the lambda appears in the code.

• Lambdas may use final local variables or effectively final local variables.

• A lambda that refers to a local variable in the enclosing lexical scope is known as a capturing lambda.

• A lambda can use the outer class’s this reference without qualifying it with the outer class’s name.

• The parameter names and variable names that you use in lambdas cannot be the same as any other local variables in the lambda’s lexical scope; otherwise, a compilation error occurs.

Section 17.3.2 Terminal Operations count, min, max, sum and average

• Class IntStream provides terminal operations for common stream reductions—count returns the number of elements, min returns the smallest int, max returns the largest int, sum returns the sum of all the ints and average returns an OptionalDouble (package java.util) containing the average of the ints as a value of type double.

• Class OptionalDouble’s getAsDouble method returns the double in the object or throws a NoSuchElementException. To prevent this exception, you can call method orElse, which returns the OptionalDouble’s value if there is one, or the value you pass to orElse, otherwise.

IntStream method summaryStatistics performs the count, min, max, sum and average operations in one pass of an IntStream’s elements and returns the results as an IntSummaryStatistics object (package java.util).

Section 17.3.3 Terminal Operation reduce

• You can define your own reductions for an IntStream by calling its reduce method. The first argument is a value that helps you begin the reduction operation and the second argument is an object that implements the IntBinaryOperator functional interface.

• Method reduce’s first argument is formally called an identity value —a value that, when combined with any stream element using the IntBinaryOperator produces that element’s original value.

Section 17.3.4 Intermediate Operations: Filtering and Sorting IntStream Values

• You filter elements to produce a stream of intermediate results that match a predicate. IntStream method filter receives an object that implements the IntPredicate functional interface (package java.util.function).

IntStream method sorted (a lazy operation) orders the elements of the stream into ascending order (by default). All prior intermediate operations in the stream pipeline must be complete so that method sorted knows which elements to sort.

• Method filter a stateless intermediate operation—it does not require any information about other elements in the stream in order to test whether the current element satisfies the predicate.

• Method sorted is a stateful intermediate operation that requires information about all of the other elements in the stream in order to sort them.

• Interface IntPredicate’s default method and performs a logical AND operation with shortcircuit evaluation between the IntPredicate on which it’s called and its IntPredicate argument.

• Interface IntPredicate’s default method negate reverses the boolean value of the IntPredicate on which it’s called.

• Interface IntPredicate default method or performs a logical OR operation with shortcircuit evaluation between the IntPredicate on which it’s called and its IntPredicate argument.

• You can use the interface IntPredicate default methods to compose more complex conditions.

Section 17.3.5 Intermediate Operation: Mapping

• Mapping is an intermediate operation that transforms a stream’s elements to new values and produces a stream containing the resulting (possibly different type) elements.

IntStream method map (a stateless intermediate operation; p. 742) receives an object that implements the IntUnaryOperator functional interface (package java.util.function).

Section 17.3.6 Creating Streams of ints with IntStream Methods range and rangeClosed

IntStream methods range and rangeClosed each produce an ordered sequence of int values. Both methods take two int arguments representing the range of values. Method range produces a sequence of values from its first argument up to, but not including, its second argument.

Method rangeClosed produces a sequence of values including both of its arguments.

Section 17.4 Stream<Integer> Manipulations

• Class Array’s stream method is used to create a Stream from an array of objects.

Section 17.4.1 Creating a Stream<Integer>

• Interface Stream (package java.util.stream) is a generic interface for performing stream operations on objects. The types of objects that are processed are determined by the Stream’s source.

• Class Arrays provides overloaded stream methods for creating IntStreams, LongStreams and DoubleStreams from int, long and double arrays or from ranges of elements in the arrays.

Section 17.4.2 Sorting a Stream and Collecting the Results

Stream method sorted sorts a stream’s elements into ascending order by default.

• To create a collection containing a stream pipeline’s results, you can use Stream method collect (a terminal operation). As the stream pipeline is processed, method collect performs a mutable reduction operation that places the results into an object, such as a List, Map or Set.

• Method collect with one argument receives an object that implements interface Collector (package java.util.stream), which specifies how to perform the mutable reduction.

• Class Collectors (package java.util.stream) provides static methods that return predefined Collector implementations.

Collectors method toList transforms a Stream<T> into a List<T> collection.

Section 17.4.3 Filtering a Stream and Storing the Results for Later Use

Stream method filter (p. 745) receives a Predicate and results in a stream of objects that match the Predicate. Predicate method test returns a boolean indicating whether the argument satisfies a condition. Interface Predicate also has methods and, negate and or.

Section 17.4.5 Sorting Previously Collected Results

• Once you place the results of a stream pipeline into a collection, you can create a new stream from the collection for performing additional stream operations on the prior results.

Section 17.5.1 Mapping Strings to Uppercase Using a Method Reference

Stream method map maps each element to a new value and produces a new stream with the same number of elements as the original stream.

• A method reference is a shorthand notation for a lambda expression.

ClassName::instanceMethodName represents a method reference for an instance method of a class. Creates a one-parameter lambda that invokes the instance method on the lambda’s argument and returns the method’s result.

objectName::instanceMethodName represents a method reference for an instance method that should be called on a specific object. Creates a one-parameter lambda that invokes the instance method on the specified object—passing the lambda’s argument to the instance method—and returns the method’s result.

ClassName::staticMethodName represents a method reference for a static method of a class.

Creates a one-parameter lambda in which the lambda’s argument is passed to the specified a static method and the lambda returns the method’s result.

ClassName::new represents a constructor reference. Creates a lambda that invokes the no-argument constructor of the specified class to create and initialize a new object of that class.

Section 17.5.2 Filtering Strings Then Sorting Them in Case-Insensitive Ascending

Order

Stream method sorted can receive a Comparator as an argument to specify how to compare stream elements for sorting.

• By default, method sorted uses the natural order for the stream’s element type.

• For Strings, the natural order is case sensitive, which means that "Z" is less than "a". Passing the predefined Comparator String.CASE_INSENSITIVE_ORDER performs a case-insensitive sort.

Section 17.5.3 Filtering Strings Then Sorting Them in Case-Insensitive Descending

Order

• Functional interface Comparator’s default method reversed reverses an existing Comparator’s ordering.

Section 17.6.1 Creating and Displaying a List<Employee>

• When the instance method reference System.out::println is passed to Stream method forEach, it’s converted by the compiler into an object that implements the Consumer functional interface.

This interface’s accept method receives one argument and returns void. In this case, the accept method passes the argument to the System.out object’s println instance method.

Section 17.6.2 Filtering Employees with Salaries in a Specified Range

• To reuse a lambda, you can assign it to a variable of the appropriate functional interface type.

• The Comparator interface’s static method comparing  receives a Function that’s used to extract a value from an object in the stream for use in comparisons and returns a Comparator object.

• A nice performance feature of lazy evaluation is the ability to perform short circuit evaluation — that is, to stop processing the stream pipeline as soon as the desired result is available.

Stream method findFirst is a short-circuiting terminal operation that processes the stream pipeline and terminates processing as soon as the first object from the stream pipeline is found. The method returns an Optional containing the object that was found, if any.

Section 17.6.3 Sorting Employees By Multiple Fields

• To sort objects by two fields, you create a Comparator that uses two Functions. First you call Comparator method comparing to create a Comparator with the first Function. On the resulting Comparator, you call method thenComparing with the second Function. The resulting Comparator compares objects using the first Function then, for objects that are equal, compares them by the second Function.

Section 17.6.4 Mapping Employees to Unique Last Name Strings

• You can map objects in a stream to different types to produce another stream with the same number of elements as the original stream.

Stream method distinct eliminates duplicate objects in a stream.

Section 17.6.5 Grouping Employees By Department

Collectors static method groupingBy with one argument receives a Function that classifies objects in the stream—the values returned by this function are used as the keys in a Map. The corresponding values, by default, are Lists containing the stream elements in a given category.

Map method forEach performs an operation on each key–value pair. The method receives an object that implements functional interface BiConsumer. This interface’s accept method has two parameters. For Maps, the first represents the key and the second the corresponding value.

Section 17.6.6 Counting the Number of Employees in Each Department

Collectors static method groupingBy with two arguments receives a Function that classifies the objects in the stream and another Collector (known as the downstream Collector).

Collectors static method counting returns a Collector that counts the number of objects in a given classification, rather than collecting them into a List.

Section 17.6.7 Summing and Averaging Employee Salaries

Stream method mapToDouble maps objects to double values and returns a DoubleStream.

The method receives an object that implements the functional interface ToDoubleFunction (package java.util.function). This interface’s applyAsDouble method invokes an instance method on an object and returns a double value.

Section 17.7 Creating a Stream<String> from a File

Files method lines creates a Stream<String> for reading the lines of text from a file.

Stream method flatMap receives a Function that maps an object into a stream—e.g., a line of text into words.

Pattern method splitAsStream uses a regular expression to tokenize a String.

Collectors method groupingBy with three arguments receives a classifier, a Map factory and a downstream Collector. The classifier is a Function that returns objects which are used as keys in the resulting Map. The Map factory is an object that implements interface Supplier and returns a new

Map collection. The downstream Collector determines how to collect each group’s elements.

Map method entrySet returns a Set of Map.Entry objects containing the Map’s key–value pairs.

Set method stream returns a stream for processing the Set’s elements.

Section 17.8 Generating Streams of Random Values

• Class SecureRandom’s methods ints, longs and doubles (inherited from class Random) return IntStream, LongStream and DoubleStream, respectively, for streams of random numbers.

• Method ints with no arguments creates an IntStream for an infinite stream of random int values. An infinite stream is a stream with an unknown number of elements—you use a short-circuiting terminal operation to complete processing on an infinite stream.

• Method ints with a long argument creates an IntStream with the specified number of random int values.

• Method ints with two int arguments creates an IntStream for an infinite stream of random int values in the range starting with the first argument and up to, but not including, the second.

• Method ints with a long and two int arguments creates an IntStream with the specified number of random int values in the range starting with the first argument and up to, but not including, the second.

• To convert an IntStream to a Stream<Integer> call IntStream method boxed.

Function static method identity creates a Function that simply returns its argument.

Section 17.9 Lambda Event Handlers

• Some event-listener interfaces are functional interfaces. For such interfaces, you can implement event handlers with lambdas. For a simple event handler, a lambda significantly reduces the amount of code you need to write.

Section 17.10 Additional Notes on Java SE 8 Interfaces

• Functional interfaces must contain only one abstract method, but may also contain default methods and static methods that are fully implemented in the interface declarations.

• When a class implements an interface with default methods and does not override them, the class inherits the default methods’ implementations. An interface’s designer can now evolve an interface by adding new default and static methods without breaking existing code that implements the interface.

• If one class inherits the same default method from two interfaces, the class must override that method; otherwise, the compiler will generate a compilation error.

• You can create your own functional interfaces by ensuring that each contains only one abstract method and zero or more default or static methods.

• You can declare that an interface is a functional interface by preceding it with the @Functional-

Interface annotation. The compiler will then ensure that the interface contains only one abstract method; otherwise, it’ll generate a compilation error.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值