Lambda
参考自:https://blog.csdn.net/holmofy/article/details/77481304
lambda:
FunctionalInterface函数式接口
四个基本函数式接口
Function<T,R> apply(T t): 输入类型T,返回类型R
Consumer<T> accept(T t):输入类型T,消费掉,无返回
Supplier(T t) T get():无输入,返回T
Predicate<T> test(T t):输入T类型,返回布尔类型
数据类型函数式接口
因为java泛型不支持基本数据类型,又因为频繁的对基本数据类型进行拆箱、封箱的操作
会影响效率问题,所以提供了基本数据类型的函数式接口。
用法同上,只是方法名不同。
一元函数式接口(用于数据类型转换)
二元函数式接口
其他函数式接口
lambda语法
// 用于替换匿名内部类,本身就是一个接口实现
public static void main(String[] args) {
new Thread(() -> printMessage("呵呵哒")).start();
}
public static void printMessage(String msg) {
System.out.println(Thread.currentThread().getId()+"-> 哈罗单车");
}
// lambda调用方法
Stream api
层级
Stream:代表通用的引用类型的流式操作接口
IntStream:代表int类型的流式操作接口,避免了int和Integer之间频繁的拆装箱操作
LongStream:代表long类型的流式操作接口,避免了long和Long之间频繁的拆装箱操作
DoubleStream:代表double类型的流式操作接口,避免了double和Double之间频繁的拆装箱操作
这几个接口的访问属性是包级别的,无法直接访问,可以通过StreamSupport工厂类去创建。
int[] arr = {20,4,26,9};
OfInt splInt = Spliterators.spliterator(arr, 0,arr.length,Spliterator.ORDERED | Spliterator.IMMUTABLE);
IntStream is = StreamSupport.intStream(splInt,false);
is.map(i -> i*i)
.filter(i -> i%2==0)
.forEach(System.out::println);
--以上代码可以简化
//简化1
Arrays.stream(arr).map(i -> i*i)
.filter(i -> i%2==0)
.forEach(System.out::println);
//简化2
IntStream.of(5,7,3,9,25,11).map(i -> i*i)
.filter(i -> i%2==0)
.forEach(System.out::println);
--简化2内部还是调用了简化1里面的内容
特点
无存储性
流并不是用来存储数据的,相反它是用来从别的数据结构中获取数据加以计算并作出对应的转换。
函数式编程
不会改变原始对象,会生成一个新的对象。
惰性求值
许多Stream的操作都是惰性实现的,目的是为了优化程序的计算,操作分为两种,中间操作和终断操作,中间操作都是惰性操作。
无限数据处理
集合的大小是有限的,但是流可以对无限的数据进行处理。
一次性消费
流的操作是一次性的,再次使用就是一个新的流对象了。
分类
中间操作
不改变原有数据源,每次操作都返回一个Stream。
无状态操作:
操作中的元素不受前后元素的影响(map filter...)。
有状态操作:
操作中的元素受前后元素的影响(sorted limit distinct....)。
终断操作
遍历流并产生结果或者副作用,一次性消费,每次都是一个新的Stream。大多数情况下终断操作都是即时的,
单iterator和spliterator除外,提供给用户自己控制数据源的遍历或者以有方式无法满足的情况。
短路操作:
非短路操作:
详解
中间操作:
无状态操作:
1、map(map,mapToInt,mapToLong,mapToDouble,mapToFloat...)
mapToxxx: 将所有元素转换为对应的int类型
flatToxxx:将所有元素转换为对应原始类型的Stream对象
2、filter过滤
3、peek 非消费型遍历
作用于map相同,不同的是并不会消费掉Stream
有状态操作:
1、distinct
2、sorted
// 按照Comparable定义的规则进行排序,前提是实现了Comparable接口
Stream<T> sorted ()
// 按照Comparator接口的方式实现排序,可以不实现Comparable接口
Stream<T> sorted(Comparator<? super T> comparator)
3、limit&skip
limit:从头截取元素
skip:从头开始跳过元素
IntStream.of(5,7,3,9,25,11,98,234,234).skip(5).limit(2).forEach(System.out::println);
终断操作:
短路操作:
anyMatch:成功一个返回true,全部失败返回false
noneMatch:成功一个返回false,全部失败返回true
allMatch:失败一个返回fasle,全部成功返回true
--这些操作都是断路操作,和中间操作同时进行,惰性求值。
非短路操作:
1、forEach、forEachOrdered
二者不同的是后者实现了顺序性,所以效率可能不如前者。
// 顺序执行 Stream.of("A","B","D","E").sequential().forEach(System.out::print);
Stream.of("A","B","E","D").sequential().forEachOrdered(System.out::print);
System.out.println();
// 并行遍历
Stream.of("A","B","D","E").parallel().forEach(System.out::print);
Stream.of("A","B","E","D").parallel().forEachOrdered(System.out::print);
// 输出
ABDEABED
DEBAABED
2、reduce
//使用reduce(BinaryOperator<T> accumulator)
Optional<String> ons = Stream.of("BAIDU","ALIBABA","DOG","ETCNM")
.reduce((s1, s2) -> {
System.out.println(s1+"->"+s2);
return s1.length()>s2.length()?s1:s2;
});
String str = ons.get();
System.out.println(str);
// 使用max
Optional<String> ons2 = Stream.of("BAIDU","ALIBABA","DOG","ETCNM")
.max((s1,s2) -> s1.length() - s2.length());
String str2 = ons2.get();
System.out.println(str2);
//使用reduce(T identity,BinaryOperator<T> accumulator)
String ons3 = Stream.of("BAIDU","ALIBABA","DOG","ETCNM")
.reduce("piupiupiu",(s1, s2) -> {
System.out.println(s1+"->"+s2);
return s1.length()>s2.length()?s1:s2;
});
System.out.println(ons3);
//
int ons4 = Stream.of("BAIDU","ALIBABA","DOG","ETCNM")
.reduce(0,(acc, sr2) -> acc+sr2.length(),(len1, len2) ->{System.out.println(len1+"->"+len2);return len1 + len2;});
System.out.println(ons4);
3、collector
// 1、集合收集器
// toCollection(支持所有实现Collection的类)
Stream.of("TEA", "BANANA", "APPLE", "ORANGE").collect(Collectors.toCollection(ArrayList::new));
// toList,流转化为List(实际上是ArrayList)
Stream.of("TEA", "BANANA", "APPLE", "ORANGE").collect(Collectors.toList());
// toSet,流转化为Set(实际上是HashSet)
Stream.of("TEA", "BANANA", "APPLE", "ORANGE").collect(Collectors.toSet());
// 2、map映射收集器
/* Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper)
*/
Person per1 = new Person("1","王五");
Person per2 = new Person("2","张三");
Map<String, String> map1 = Stream.of(per1,per2).collect(Collectors.toMap(Person::getCode, Person::getName));
Set<Map.Entry<String, String>> set1 = map1.entrySet();
for(Map.Entry<String, String> en:set1) {
System.out.println(en.getKey() +" -> "+en.getValue());
}
/*
key相同的方法,对value进行处理(只能是二个key相等)
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
*/
per2 = new Person("1","张三");
Map<String, String> map2 = Stream.of(per1,per2).collect(Collectors.toMap(Person::getCode, Person::getName,(s, a) -> s+"->"+a));
Set<Map.Entry<String, String>> set2 = map2.entrySet();
for(Map.Entry<String, String> en:set2) {
System.out.println(en.getKey() +" -> "+en.getValue());
}
/*
***********************************************************
// mapSupplier提供Map的实现类
public static <T, K, U, M extends Map<K, U>> Collector<T, ?, M>
toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier);
***********************************************************
// 转成ConcurrentMap(默认创建ConcurrentHashMap)
public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>>
toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper);
public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>>
toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction);
public static <T, K, U, M extends ConcurrentMap<K, U>> Collector<T, ?, M>
toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier)
*/
// 3、分组操作
Map<Boolean, List<String>> qrCode = Stream.of("Hello", "Lambda", "Hello", "Java").collect(Collectors.partitioningBy(str -> str.startsWith("H")));
Set<Map.Entry<Boolean, List<String>>> set6 = qrCode.entrySet();
for(Map.Entry<Boolean, List<String>> en:set6) {
System.out.println(en.getKey() +" -> "+en.getValue());
List<String> es = en.getValue();
for (String e:es) {
System.out.println(e);
}
}
// 4、字符串拼接
public static Collector<CharSequence, ?, String> joining();
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter);
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix);
--示例:
String strConcat = Stream.of("Hello", "Lambda", "Hello", "Java").collect(Collectors.joining("$","{","}"));
System.out.println(strConcat);
// {Hello$Lambda$Hello$Java}
扩展(Comparable,comparator接口)
参考地址:
1、https://blog.csdn.net/holmofy/article/details/77481304#2-sorted排序
2、https://blog.csdn.net/wenzhi20102321/article/details/52494402 3、https://blog.csdn.net/lx_nhs/article/details/78871295
4、https://www.cnblogs.com/liujinhong/p/6113183.html
5、https://blog.csdn.net/kris1025/article/details/85861196
6、https://www.cnblogs.com/mengzj233/p/9816289.html
7、https://www.cnblogs.com/mengzj233/p/9816289.html
1、Comparable接口
内部实现的排序,集合内部的对象本身需要实现Comparable接口,然后借助Collections工具类的方法进行排序。
2、comparator接口
外部实现的排序,使用Collections工具类的方法传入集合,然后指定comparator接口的实现进行排序,使用了一种策略模式,不改变自身,使用一个策略对象来改变它的行为。
int[]和List互换
https://blog.csdn.net/PitBXu/article/details/97672145
求最大值:
https://blog.csdn.net/u012190514/article/details/83036610
local varable must be null
https://blog.csdn.net/weixin_38883338/article/details/89195749
字符串格式化:https://blog.csdn.net/rlk512974883/article/details/80829985