函数式编程
观点和原则
lambda表达式
纯函数
引用透明性
初等函数
高阶函数
组合
柯里化
闭包
不可变性
函子
加强版函子
单子
lambda
之前是通过使用匿名类来实现,处于性能(匿名实现方式需要加载太多的生成类)和定制化(未来的变化)的考虑,其实现方式使用java7中引入的动态调用而不是匿名类
纯函数
针对相同的输入总会产生相同的输出
例子
写入到文件/控制台/网络/屏幕
修改外部变量/状态
调用非纯函数
启动进程
引用透明性
函数针对相同的输入得到相同返回值得一种属性,针对特定函数,大大有利于提高存储效率(将返回结果缓存)和并发性
初等函数
进行创建、存储、用作参数、用作返回值
高阶函数
将其他函数作为参数,可以创建和返回函数,还可以利用现有和经过测试的小型函数进行代码重用
组合
顾名思义
柯里化
将n元函数转换为一系列一元函数
闭包
实现词法作用域的技术
允许我们在内部作用域中访问外部上下文变量
使用要谨慎,根据经验,常使用final关键词限制其更改
不可变性
提示不可变性能够使代码更加简洁,有利于开发专注于流程而不是代码可能产生的副作用
函子functor
允许将函数应用于给定的容器
加强版函子applicative
函数不仅仅应用于对象,也对函数进行了包装
单子monad
应用于接受包装值并返回包装值得函数
函数式编程
lambda
使用lambda 表达式的重点是延迟执行。如果想要立即执行的话就无需lambda。之所以希望延迟执行,原因如下:
在一个单独的线程中运行
多次运行代码
在算法的适当位置运行代码(例如排序中的比较操作)
发生某种情况时执行代码(如点击了一个按钮、数据到达等)
只在必要时才运行代码
通过使用addThen可以将BiConsumer连接起来
Consumer和BiConsumer<T,U>
输入参数不返回结果的操作
import java. util. HashMap;
import java. util. Map;
import java. util. function. BiConsumer;
import java. util. function. Consumer;
public class BiConsumerDemo {
public static void main ( String[ ] args) {
HashMap map = new HashMap ( ) ;
map. put ( 100 , "三个人" ) ;
map. put ( 110 , "四个人" ) ;
map. put ( 115 , "五个人" ) ;
map. put ( 120 , "一群人" ) ;
Consumer< Map> consumer = x - > {
x. forEach ( ( k, v) - > System. out. println ( "key:" + k+ "value:" + v) ) ;
} ;
consumer. accept ( map) ;
HashMap mapMonkey = new HashMap ( ) ;
mapMonkey. put ( 100 , "三只猴" ) ;
mapMonkey. put ( 110 , "四只猴" ) ;
mapMonkey. put ( 115 , "五只猴" ) ;
mapMonkey. put ( 120 , "一群猴" ) ;
BiConsumer< Map, Consumer> biConsumer = ( map1, consumer1) - >
{
consumer1. accept ( map1) ;
} ;
biConsumer. accept ( mapMonkey, consumer) ;
}
}
BiFunction
BiFunction<T, U, R>表示可以接收两个参数,返回一个结果。T,U分别表示第一,第二个参数,R表示结果。
BiFuntion可以用lambda表达式来实现。
import java. util. HashMap;
import java. util. Map;
import java. util. function. BiConsumer;
import java. util. function. BiFunction;
import java. util. function. Consumer;
public class BiFunctionDemo {
public static void main ( String[ ] args) {
BiFunction< Integer, Integer, Integer> add = ( x, y) - > x + y;
System. out. println ( add. apply ( 1 , 2 ) ) ;
Calculator calculator = new Calculator ( ) ;
System. out. println ( calculator. cal ( ( a, b) - > a + b, "aaa" , "bbb" ) ) ;
}
}
class Calculator {
public String cal ( BiFunction< String, String, String> bi, String a, String b) {
return bi. apply ( a, b) ;
}
}
BinaryOperator
BinaryOperator<T>函数式接口是BiFunction<T,T,T>的子接口,它接受2个都是T类型的参数,并且返回T类型的结果
import java. util. Comparator;
import java. util. HashMap;
import java. util. Map;
import java. util. function. BiConsumer;
import java. util. function. BiFunction;
import java. util. function. BinaryOperator;
import java. util. function. Consumer;
public class BinaryOperatorDemo {
public static void main ( String[ ] args) {
BinaryOperator< String> joinOperator = ( t1, t2) - > t1 + "," + t2;
String str = joinOperator. apply ( "Hello" , "World" ) ;
System. out. println ( "str:" + str) ;
BinaryOperator< Integer> minOperator = BinaryOperator. minBy ( Comparator. naturalOrder ( ) ) ;
Integer minInt = minOperator. apply ( 203 , 500 ) ;
System. out. println ( "minInt:" + minInt) ;
BinaryOperator< String> maxOperator = BinaryOperator. maxBy ( Comparator. naturalOrder ( ) ) ;
String maxStr = maxOperator. apply ( "ABC" , "anc" ) ;
System. out. println ( "maxStr:" + maxStr) ;
}
}
BiPredicate<T,U>
在java.util中定义的谓词<T>接口。功能包。它表示一个只有一个参数的布尔值函数。它是一种函数接口,其函数方法是test()。BiPredicate<T, U>接口与具有两个参数的Predicate<T>接口类似。它可以用作lambda表达式的赋值目标
@FunctionalInterface
public interface BiPredicate < T, U> {
boolean test ( T t, U u) ;
}
import java. util. Arrays;
import java. util. List;
import java. util. function. BiPredicate;
import java. util. stream. Collectors;
public class BiPredicateDemo {
public static void main ( String[ ] args) {
BiPredicate< String, Integer> filter = ( x, y) - > {
return x. length ( ) == y;
} ;
boolean result = filter. test ( "mkyong" , 6 ) ;
System. out. println ( result) ;
boolean result2 = filter. test ( "java" , 10 ) ;
System. out. println ( result2) ;
List< Domain> domains = Arrays. asList ( new Domain ( "google.com" , 1 ) ,
new Domain ( "i-am-spammer.com" , 10 ) ,
new Domain ( "mkyong.com" , 0 ) ,
new Domain ( "microsoft.com" , 2 ) ) ;
BiPredicate< String, Integer> bi = ( domain, score) - > {
return ( domain. equalsIgnoreCase ( "google.com" ) || score == 0 ) ;
} ;
List< Domain> result11 = filterBadDomain ( domains, bi) ;
System. out. println ( result11) ;
List< Domain> result22 = filterBadDomain ( domains, ( domain, score) - > score == 0 ) ;
System. out. println ( result22) ;
List< Domain> result3 = filterBadDomain ( domains, ( domain, score) - > domain. startsWith ( "i" ) && score > 5 ) ;
System. out. println ( result3) ;
List< Domain> result4 = filterBadDomain ( domains, bi. or (
( domain, x) - > domain. equalsIgnoreCase ( "microsoft.com" ) )
) ;
System. out. println ( result4) ;
}
public static < T extends Domain > List< T> filterBadDomain (
List< T> list, BiPredicate< String, Integer> biPredicate) {
return list. stream ( )
. filter ( x - > biPredicate. test ( x. getName ( ) , x. getScore ( ) ) )
. collect ( Collectors. toList ( ) ) ;
}
}
class Domain {
String name;
Integer score;
public Domain ( String name, Integer score) {
this . name = name;
this . score = score;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public Integer getScore ( ) {
return score;
}
public void setScore ( Integer score) {
this . score = score;
}
@Override
public String toString ( ) {
return "Domain [name=" + name + ", score=" + score + "]" ;
}
}
Function<T,R>
R apply(T t) : 将对象对应到输入参数上并返回计算结果
default<V> Function<T,V> : 将两个fuction整合,然后返回一个能执行两个Function对象功能的Function对象
除apply还有以下接口:
default <V> Function<T,V> andThen(Function<? super R,? extends V> after) 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。
default <V> Function<T,V> compose(Function<? super V,? extends T> before)返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象。
static <T> Function<T,T> identity() 返回一个执行了apply()方法之后只会返回输入参数的函数对象
default < V> Function< V, R> compose ( Function< ? super V, ? extends T > before) {
Objects. requireNonNull ( before) ;
return ( V v) - > apply ( before. apply ( v) ) ;
}
import java. util. ArrayList;
import java. util. List;
import java. util. Map;
import java. util. function. Consumer;
import java. util. function. Function;
import java. util. function. ToIntFunction;
import java. util. stream. Collectors;
import java. util. stream. Stream;
public class FunctionDemo {
public static void main ( String[ ] args) {
Function< Integer, Integer> test= i- > i+ 1 ;
test. apply ( 5 ) ;
Function< Integer, Integer> A= i- > i+ 1 ;
Function< Integer, Integer> B= i- > i* i;
System. out. println ( "F1:" + B. apply ( A. apply ( 5 ) ) ) ;
System. out. println ( "F1:" + B. compose ( A) . apply ( 5 ) ) ;
System. out. println ( "F2:" + A. apply ( B. apply ( 5 ) ) ) ;
System. out. println ( "F2:" + B. andThen ( A) . apply ( 5 ) ) ;
Stream< String> stream = Stream. of ( "I" , "love" , "you" , "too" ) ;
Map< String, Integer> map = stream. collect ( Collectors. toMap ( Function. identity ( ) , String: : length) ) ;
Consumer< Map> consumer = x - > {
x. forEach ( ( k, v) - > System. out. println ( "key:" + k+ " value:" + v) ) ;
} ;
consumer. accept ( map) ;
}
}
Predicate
是个断言式接口其参数是<T,boolean>,也就是给一个参数T,返回boolean类型的结果。跟Function一样,Predicate的具体实现也是根据传入的lambda表达式来决定的。
@FunctionalInterface
public interface Predicate < T> {
boolean test ( T t) ;
default Predicate< T> and ( Predicate< ? super T> other) {
Objects. requireNonNull ( other) ;
return ( t) - > test ( t) && other. test ( t) ;
}
default Predicate< T> negate ( ) {
return ( t) - > ! test ( t) ;
}
default Predicate< T> or ( Predicate< ? super T> other) {
Objects. requireNonNull ( other) ;
return ( t) - > test ( t) || other. test ( t) ;
}
static < T> Predicate< T> isEqual ( Object targetRef) {
return ( null == targetRef)
? Objects: : isNull
: object - > targetRef. equals ( object) ;
}
}
package functional_programming. lambda;
import java. util. function. Predicate;
public class PredicateDemo {
public static void main ( String[ ] args) {
Predicate< Integer> predicate = x - > x > 7 ;
System. out. println ( predicate. test ( 10 ) ) ;
System. out. println ( predicate. test ( 6 ) ) ;
predicate = predicate. and ( x - > x % 2 == 0 ) ;
System. out. println ( predicate. test ( 6 ) ) ;
System. out. println ( predicate. test ( 12 ) ) ;
System. out. println ( predicate. test ( 13 ) ) ;
predicate = x - > x > 5 && x < 9 ;
System. out. println ( predicate. test ( 10 ) ) ;
System. out. println ( predicate. test ( 6 ) ) ;
}
}
class User {
private String name;
private String sex;
private Integer age;
public User ( ) {
super ( ) ;
}
public User ( String name, String sex, Integer age) {
super ( ) ;
this . name = name;
this . sex = sex;
this . age = age;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public String getSex ( ) {
return sex;
}
public void setSex ( String sex) {
this . sex = sex;
}
public Integer getAge ( ) {
return age;
}
public void setAge ( Integer age) {
this . age = age;
}
@Override
public boolean equals ( Object obj) {
if ( obj instanceof User ) {
User user = ( User) obj;
if ( name. equals ( user. name) ) {
return true ;
}
}
return false ;
}
@Override
public int hashCode ( ) {
return name. hashCode ( ) ;
}
}
Supplier
java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
@FunctionalInterface
public interface Supplier < T> {
T get ( ) ;
}
import java. util. function. Supplier;
public class SupplierDemo {
public static void main ( String[ ] args) {
String msgA = "Hello " ;
String msgB = "World " ;
System. out. println (
getString (
( ) - > msgA + msgB
)
) ;
}
private static String getString ( Supplier< String> stringSupplier) {
return stringSupplier. get ( ) ;
}
}
UnaryOperator
一元运算,接受一个T类型参数,输出一个与入参一模一样的值
package java. util. function;
@FunctionalInterface
public interface UnaryOperator < T> extends Function < T, T> {
static < T> UnaryOperator< T> identity ( ) {
return t - > t;
}
}
import java. util. function. UnaryOperator;
public class UnaryOperatorDemo {
public static void main ( String[ ] args) {
System. out. println ( UnaryOperator. identity ( ) . apply ( 10 ) ) ;
System. out. println ( UnaryOperator. identity ( ) . apply ( 10.01 ) ) ;
System. out. println ( UnaryOperator. identity ( ) . apply ( false ) ) ;
System. out. println ( UnaryOperator. identity ( ) . apply ( "10" ) ) ;
UnaryOperator< Integer> b = x- > x. intValue ( ) ;
System. out. println ( b. apply ( 10 ) ) ;
}
}
流
Stream
Iterator< T> iterator ( ) ;
Spliterator< T> spliterator ( ) ;
boolean isParallel ( ) ;
S sequential ( ) ;
S parallel ( ) ;
S unordered ( ) ;
S onClose ( Runnable closeHandler) ;
void close ( ) ;
import java. io. Serializable;
import java. util. stream. DoubleStream;
import java. util. stream. IntStream;
import java. util. stream. LongStream;
import java. util. stream. Stream;
public class StreamStartDemo {
public static void main ( String[ ] args) {
Integer[ ] nums = new Integer [ 10 ] ;
Stream< Integer> stream0 = Arrays. stream ( nums) ;
Stream< Integer> stream = Stream. of ( 1 , 2 , 3 , 4 , 5 , 6 ) ;
stream. forEach ( System. out: : println) ;
System. out. println ( "---------------------" ) ;
Stream< Integer> stream2 = Stream. iterate ( 0 , ( x) - > x + 2 ) . limit ( 6 ) ;
stream2. forEach ( System. out: : println) ;
System. out. println ( "---------------------" ) ;
Stream< Double> stream3 = Stream. generate ( Math: : random) . limit ( 2 ) ;
stream3. forEach ( System. out: : println) ;
System. out. println ( "-------------------" ) ;
IntStream intstream = IntStream. empty ( ) ;
System. out. println ( "intstream" + intstream. count ( ) ) ;
IntStream. Builder b = IntStream. builder ( ) ;
b. add ( 1 ) ;
b. add ( 2 ) ;
b. add ( 3 ) ;
b. add ( 4 ) ;
b. build ( ) . forEach ( System. out: : println) ;
IntStream. range ( 0 , 10 ) . forEach ( i - > System. out. println ( i) ) ;
IntStream. rangeClosed ( 0 , 10 ) . forEach ( i - > System. out. println ( i) ) ;
Integer[ ] arr = { 1 , 2 , 3 , 4 , 5 , 6 } ;
Stream< Integer> arr1 = Stream. of ( arr) ;
Stream< String> stringStream = Stream. of ( "a" , "b" , "x" , "d" ) ;
Stream< ? extends Serializable > concat = Stream. concat ( arr1, stringStream) ;
concat. forEach ( str- > System. out. println ( str) ) ;
System. out. println ( "---------------------------" ) ;
LongStream longstream = LongStream. empty ( ) ;
System. out. println ( longstream. count ( ) ) ;
LongStream longstream_range = LongStream. range ( 6 L, 10 L) ;
longstream_range. forEach ( System. out: : println) ;
System. out. println ( "---------------------------" ) ;
DoubleStream doublestream = DoubleStream. empty ( ) ;
System. out. println ( doublestream. count ( ) ) ;
}
}
package functional_programming. stream;
import java. util. ArrayList;
import java. util. Arrays;
import java. util. Comparator;
import java. util. List;
import java. util. concurrent. TimeUnit;
import java. util. stream. Collectors;
import java. util. stream. Stream;
public class StreamIn {
public static void main ( String[ ] args) throws Exception {
List< String> seriallist = new ArrayList < String> ( ) ;
for ( int i= 0 ; i< 1000000 ; i++ ) {
double dserial = Math. random ( ) * 1000 ;
seriallist. add ( dserial+ "" ) ;
}
long startserial = System. nanoTime ( ) ;
int countserial= ( int ) ( ( Stream) seriallist. stream ( ) . sequential ( ) ) . sorted ( ) . count ( ) ;
long endserial = System. nanoTime ( ) ;
long msserial = TimeUnit. NANOSECONDS. toMillis ( endserial- startserial) ;
System. out. println ( "串行化花费时间:" + msserial+ "ms" ) ;
System. out. println ( "============================" ) ;
List< String> parallellist = new ArrayList < String> ( ) ;
for ( int i= 0 ; i< 1000000 ; i++ ) {
double dserial= Math. random ( ) * 1000 ;
parallellist. add ( dserial+ "" ) ;
}
long startparallel = System. nanoTime ( ) ;
int countparallel = ( int ) ( ( Stream) parallellist. stream ( ) . parallel ( ) ) . sorted ( ) . count ( ) ;
long endparallel = System. nanoTime ( ) ;
long msparallel = TimeUnit. NANOSECONDS. toMillis ( endparallel- startparallel) ;
System. out. println ( "并行化花费时间:" + msparallel+ "ms" ) ;
System. out. println ( "============================" ) ;
Stream. of ( 1 , 2 , 3 , 4 , 5 ) . forEach ( System. out: : println) ;
Stream. of ( 1 , 2 , 3 , 4 , 5 ) . unordered ( ) . forEach ( System. out: : println) ;
System. out. println ( "============================" ) ;
System. out. println ( "============================" ) ;
List< Integer> list = new ArrayList < > ( ) ;
for ( int i = 0 ; i < 10 ; i++ ) {
list. add ( i) ;
}
System. out. println ( "原列表:" ) ;
System. out. println ( list) ;
list = list. stream ( ) . filter ( a - > a % 2 == 0 ) . collect ( Collectors. toList ( ) ) ;
System. out. println ( "列表中的偶数:" ) ;
System. out. println ( list) ;
System. out. println ( "============================" ) ;
List< Integer> num = Arrays. asList ( 1 , 2 , 3 , 4 , 5 ) ;
List< Integer> collect1 = num. stream ( ) . map ( n - > n * 2 ) . collect ( Collectors. toList ( ) ) ;
System. out. println ( collect1) ;
System. out. println ( "============================" ) ;
List< String> words = Arrays. asList ( "hello c++" , "hello java" , "hello python" ) ;
List< String> result = words. stream ( )
. map ( word - > word. split ( " " ) )
. flatMap ( Arrays: : stream)
. distinct ( )
. collect ( Collectors. toList ( ) ) ;
System. out. println ( result) ;
System. out. println ( "============================" ) ;
List< String> result1 = Stream. of ( "a" , "s" , "d" , "f" )
. sorted ( Comparator. comparing ( ( String s) - > ! s. equals ( "d" ) )
. thenComparing ( Comparator. naturalOrder ( ) ) )
. collect ( Collectors. toList ( ) ) ;
System. out. println ( result1) ;
System. out. println ( "============================" ) ;
Stream. of ( "one" , "two" , "three" , "four" ) . peek ( e - > System. out. println ( e) ) . collect ( Collectors. toList ( ) ) ;
System. out. println ( "============================" ) ;
List< Integer> numbers = Arrays. asList ( 1 , 2 , 3 , 4 , 5 , 6 ) ;
System. out. println ( "skip:" ) ;
numbers. stream ( ) . skip ( 2 ) . forEach ( System. out: : println) ;
System. out. println ( "limit:" ) ;
numbers. stream ( ) . limit ( 2 ) . forEach ( System. out: : println) ;
System. out. println ( "============================" ) ;
}
}
package functional_programming. stream;
import java. util. Arrays;
import java. util. Collections;
import java. util. Comparator;
import java. util. DoubleSummaryStatistics;
import java. util. HashMap;
import java. util. Iterator;
import java. util. List;
import java. util. Map;
import java. util. Optional;
import java. util. TreeSet;
import java. util. function. Function;
import java. util. stream. Collectors;
import java. util. stream. DoubleStream;
import java. util. stream. IntStream;
import java. util. stream. Stream;
public class StreamEnd {
private final static Map< Integer, Double> xFilesSeasonPremierRatings;
static
{
final Map< Integer, Double> temporary = new HashMap < > ( ) ;
temporary. put ( 1 , 12.0 ) ;
temporary. put ( 2 , 16.1 ) ;
temporary. put ( 3 , 19.94 ) ;
temporary. put ( 4 , 21.11 ) ;
temporary. put ( 5 , 27.34 ) ;
temporary. put ( 6 , 20.24 ) ;
temporary. put ( 7 , 17.82 ) ;
temporary. put ( 8 , 15.87 ) ;
temporary. put ( 9 , 10.6 ) ;
xFilesSeasonPremierRatings = Collections. unmodifiableMap ( temporary) ;
}
public static void main ( String[ ] args) {
System. out. println ( "迭代器操作流结束" ) ;
List< String> lists = Arrays. asList ( "A" , "B" , "C" , "D" ) ;
Iterator< String> iterator = lists. stream ( ) . iterator ( ) ;
while ( iterator. hasNext ( ) ) {
System. out. println ( iterator. next ( ) ) ;
}
System. out. println ( "================================" ) ;
List< String> lists_spliterator = Arrays. asList ( "A" , "B" , "C" , "D" ) ;
lists_spliterator. stream ( ) . spliterator ( ) . forEachRemaining ( System. out: : println) ;
System. out. println ( "================================" ) ;
System. out. println ( "集合操作流结束" ) ;
int [ ] arr = IntStream. of ( 1 , 2 , 3 , 4 , 5 ) . toArray ( ) ;
System. out. println ( Arrays. toString ( arr) ) ;
Integer[ ] integers = Stream. of ( 1 , 2 , 3 , 4 , 5 ) . toArray ( Integer[ ] : : new ) ;
printArray ( integers) ;
System. out. println ( Stream. of ( "a" , "b" , "c" , "a" ) . collect ( Collectors. toSet ( ) ) ) ;
TreeSet< String> treeSet = Stream. of ( "a" , "c" , "b" , "a" ) . collect ( Collectors. toCollection ( TreeSet: : new ) ) ;
System. out. println ( treeSet) ;
Map< String, String> collect = Stream. of ( "a" , "b" , "c" , "a" ) . collect ( Collectors. toMap ( x - > x, x - > x + x, ( oldVal, newVal) - > newVal) ) ;
collect. forEach ( ( k, v) - > System. out. println ( k + ":" + v) ) ;
Map< Integer, List< Integer> > map = Stream. of ( 1 , 3 , 3 , 2 ) . collect ( Collectors. groupingBy ( Function. identity ( ) ) ) ;
System. out. println ( map) ;
Map< Integer, Integer> map1 = Stream. of ( 1 , 3 , 3 , 2 ) . collect ( Collectors. groupingBy ( Function. identity ( ) , Collectors. summingInt ( x - > x) ) ) ;
System. out. println ( map1) ;
HashMap< Integer, List< Integer> > hashMap = Stream. of ( 1 , 3 , 3 , 2 ) . collect ( Collectors. groupingBy ( Function. identity ( ) , HashMap: : new , Collectors. mapping ( x - > x + 1 , Collectors. toList ( ) ) ) ) ;
System. out. println ( hashMap) ;
Map< Boolean, List< Integer> > map_partitioningBy = Stream. of ( 1 , 3 , 3 , 2 ) . collect ( Collectors. partitioningBy ( x - > x > 2 ) ) ;
System. out. println ( map_partitioningBy) ;
Map< Boolean, Long> longMap = Stream. of ( 1 , 3 , 3 , 2 ) . collect ( Collectors. partitioningBy ( x - > x > 1 , Collectors. counting ( ) ) ) ;
System. out. println ( longMap) ;
System. out. println ( Stream. of ( "1" , "3" , "3" , "2" ) . collect ( Collectors. joining ( "," ) ) ) ;
Integer integer = Stream. of ( "1" , "2" , "3" ) . collect ( Collectors. collectingAndThen ( Collectors. toList ( ) , x - > x. size ( ) ) ) ;
System. out. println ( integer) ;
System. out. println ( Stream. of ( 1 , 3 , 5 ) . collect ( Collectors. mapping ( x - > x + 1 , Collectors. toList ( ) ) ) ) ;
System. out. println ( "================================" ) ;
System. out. println ( "特定元素操作流结束" ) ;
List< Integer> list = Arrays. asList ( 1 , 2 , 3 , 2 , 1 ) ;
Optional< Integer> first = list. stream ( ) . findFirst ( ) ;
if ( first. isPresent ( ) ) {
Integer result = first. get ( ) ;
System. out. println ( result) ;
} else {
System. out. println ( "no value?" ) ;
}
Optional< Integer> first2 = list
. stream ( )
. filter ( x - > x > 1 ) . findFirst ( ) ;
if ( first2. isPresent ( ) ) {
System. out. println ( first2. get ( ) ) ;
} else {
System. out. println ( "no value?" ) ;
}
List< Integer> blist = Arrays. asList ( 1 , 2 , 3 , 2 , 1 ) ;
int a = blist. stream ( ) . filter ( b- > 1 == 1 ) . findAny ( ) . orElse ( 0 ) ;
System. out. println ( a) ;
System. out. println ( "================================" ) ;
System. out. println ( "聚合规约操作流结束" ) ;
final DoubleSummaryStatistics doubleSummaryStatistics =
xFilesSeasonPremierRatings. values ( ) . stream ( ) . collect (
DoubleSummaryStatistics: : new ,
DoubleSummaryStatistics: : accept,
DoubleSummaryStatistics: : combine) ;
System. out. println ( "X-Files Season Premieres: " + doubleSummaryStatistics) ;
System. out. println ( DoubleStream
. builder ( )
. add ( 12.4 )
. add ( 13.6 )
. add ( 9.7 )
. add ( 24.5 )
. add ( 10.2 )
. add ( 3.0 )
. build ( ) . summaryStatistics ( ) ) ;
List< Integer> list_reduce = Arrays. asList ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ) ;
int b= list_reduce. stream ( ) . reduce ( 0 , ( x, y) - > x + y) ;
System. out. println ( b) ;
Stream< String> s = Stream. of ( "2" , "3" , "4" , "5" ) ;
Optional< String> obj = Optional. ofNullable ( s. collect ( Collectors. maxBy ( Comparator. reverseOrder ( ) ) ) . orElse ( null) ) ;
if ( obj. isPresent ( ) ) {
System. out. println ( "maxBy():" + obj. get ( ) ) ;
}
else {
System. out. println ( "no value" ) ;
}
Stream< String> ss = Stream. of ( "2" , "3" , "4" , "5" ) ;
Optional< String> obj_minBy = Optional. ofNullable ( ss. collect ( Collectors. minBy ( Comparator. reverseOrder ( ) ) ) . orElse ( null) ) ;
if ( obj_minBy. isPresent ( ) ) {
System. out. println ( "obj_minBy():" + obj_minBy. get ( ) ) ;
}
else {
System. out. println ( "no value" ) ;
}
Stream< String> sc = Stream. of ( "1" , "2" , "3" , "4" ) ;
long ans = sc. collect ( Collectors. counting ( ) ) ;
System. out. println ( ans) ;
}
private static < T> void printArray ( T[ ] arr) {
System. out. println ( arr. length) ;
System. out. println ( Arrays. toString ( arr) ) ;
}
}
parallelStream
Java 的并行 API 演变历程基本如下:
1.0-1.4 中的 java.lang.Thread
5.0 中的 java.util.concurrent
6.0 中的 Phasers 等
7.0 中的 Fork/Join 框架
8.0 中的 Lambda
其实就是一个并行执行的流.它通过默认的ForkJoinPool,可能提高你的多线程任务的速度
要想深入的研究parallelStream之前,那么我们必须先了解ForkJoin框架和ForkJoinPool.本文旨在parallelStream,但因为两种关系甚密,故在此简单介绍一下ForkJoinPool,如有兴趣可以更深入的去了解下ForkJoin***(当然,如果你想真正的搞透parallelStream,那么你依然需要先搞透ForkJoinPool).*
ForkJoin框架是从jdk7中新特性,它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口。它使用了一个无限队列来保存需要执行的任务,而线程的数量则是通过构造函数传入,如果没有向构造函数中传入希望的线程数量,那么当前计算机可用的CPU数量会被设置为线程数量作为默认值。
ForkJoinPool主要用来使用分治法(Divide-and-Conquer Algorithm)来解决问题。典型的应用比如快速排序算法。这里的要点在于,ForkJoinPool需要使用相对少的线程来处理大量的任务。比如要对1000万个数据进行排序,那么会将这个任务分割成两个500万的排序任务和一个针对这两组500万数据的合并任务。以此类推,对于500万的数据也会做出同样的分割处理,到最后会设置一个阈值来规定当数据规模到多少时,停止这样的分割处理。比如,当元素的数量小于10时,会停止分割,转而使用插入排序对它们进行排序。那么到最后,所有的任务加起来会有大概2000000+个。问题的关键在于,对于一个任务而言,只有当它所有的子任务完成之后,它才能够被执行。
所以当使用ThreadPoolExecutor时,使用分治法会存在问题,因为ThreadPoolExecutor中的线程无法像任务队列中再添加一个任务并且在等待该任务完成之后再继续执行。而使用ForkJoinPool时,就能够让其中的线程创建新的任务,并挂起当前的任务,此时线程就能够从队列中选择子任务执行。
那么使用ThreadPoolExecutor或者ForkJoinPool,会有什么性能的差异呢?
首先,使用ForkJoinPool能够使用数量有限的线程来完成非常多的具有父子关系的任务,比如使用4个线程来完成超过200万个任务。但是,使用ThreadPoolExecutor时,是不可能完成的,因为ThreadPoolExecutor中的Thread无法选择优先执行子任务,需要完成200万个具有父子关系的任务时,也需要200万个线程,显然这是不可行的。
工作窃取算法
forkjoin最核心的地方就是利用了现代硬件设备多核,在一个操作时候会有空闲的cpu,那么如何利用好这个空闲的cpu就成了提高性能的关键,而这里我们要提到的工作窃取(work-stealing)算法就是整个forkjion框架的核心理念,工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行。
那么为什么需要使用工作窃取算法呢?
假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。
default Stream< E> parallelStream ( ) {
return StreamSupport. stream ( spliterator ( ) , true ) ;
}
import java. util. ArrayList;
import java. util. Arrays;
import java. util. HashMap;
import java. util. HashSet;
import java. util. List;
import java. util. Map;
import java. util. Set;
import java. util. Vector;
import java. util. stream. Stream;
public class ParallelStreamDemo {
public static void main ( String[ ] args) {
List< Integer> numbers = Arrays. asList ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) ;
Stream< Integer> stream = Stream. of ( 1 , 2 , 3 , 4 , 5 , 6 ) ;
stream. forEach ( System. out: : println) ;
List< String> list = new ArrayList < > ( ) ;
Stream< String> stream1 = list. stream ( ) ;
Set< String> set = new HashSet < > ( ) ;
Stream< String> stream2 = set. stream ( ) ;
Vector< String> vector = new Vector < > ( ) ;
Stream< String> stream3 = vector. stream ( ) ;
Map< String, String> map = new HashMap < > ( ) ;
Stream< String> keyStream = map. keySet ( ) . stream ( ) ;
Stream< String> valueStream = map. values ( ) . stream ( ) ;
Stream< Map. Entry< String, String> > entryStream = map. entrySet ( ) . stream ( ) ;
System. out. println ( "------------------------------------------" ) ;
numbers. parallelStream ( )
. forEachOrdered ( System. out: : println) ;
Stream< Integer> stream4 = numbers. parallelStream ( ) ;
Stream< Integer> stream5 = numbers. stream ( ) . parallel ( ) ;
}
}