参考书籍:Java8 函数式编程
AndroidStudio创建一个java Module
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
这里需要将java版本设置为1.8+
public class SimpleLambda {
public static void main(String[] args){
/**
* 默认无参数 默认返回Runnable类型
*/
Runnable runnable = () -> System.out.println("Hello Lambda");
runnable.run();
Runnable runnable1 = () -> {
System.out.print("Hello");
System.out.println(" Lambda");
};
runnable1.run();
/**
* 一个参数,无返回值, 默认返回Consumer类型
*/
Consumer tConsumer = (Integer x) -> System.out.println(x);
Consumer doubleConsumer = (Double d) -> System.out.println(d);
//由方法引用代替
Consumer tConsumer1 = System.out::println;
Consumer doubleConsumer1 = System.out::println;
tConsumer.accept(10);
tConsumer1.accept(101);
doubleConsumer.accept(20.0);
doubleConsumer1.accept(201.0);
Predicate predicate = (x) -> x > 10;
System.out.println(predicate.test(10));
/**
* 两个参数,有返回值
*/
//lambda表达式默认返回类型IntBinaryOperator
IntBinaryOperator intBinaryOperator = (x, y) -> x + y;
System.out.println(intBinaryOperator.applyAsInt(3, 4));
//lambda表达式默认返回类型DoubleBinaryOperator
DoubleBinaryOperator doubleBinaryOperator = (double x, double y) -> x + y;
System.out.println(doubleBinaryOperator.applyAsDouble(3.0, 4.0));
BinaryOperator add = (x, y) -> x + y;
System.out.println(add.apply(10, 20));
}
}
总结个简单的公式:
(参数...) -> 表达式;
(参数...) -> {代码块};
这里由于java8的类型推断,参数类型可写可不写,不写底层会根据方法的参数列表推断出来。
以上代码等号右边的lambda为什么返回等号左边的类型,看到下面的函数式接口就明白了
查看原码发现,Runnable多了一个注解 @FunctionalInterface(函数式接口)
package java.lang;
@FunctionalInterface
public interface Runnable {
void run();
}
什么是函数式接口
简单说,只有一个抽象方法(不包括default static方法)的接口。
函数式接口其实就是Lambda表达式(又称为闭包)本身的类型
以下是java8中util.function包下的类,我总结了一个,分为5大种类
分别是Function, Operator, Consumer, Supplier, Predicate
Stream
我们来看看java8新引进的Stream及对集合类的改进
Arrays:将Arrays转换为Stream
String[] arrays = {"a1", "a2", "a3"};
Stream stream = Arrays.stream(arrays);
相关新加方法及重载方法:
//
public static Stream stream(T[] array) {
return stream(array, 0, array.length);
}
public static Stream stream(T[] array, int startInclusive, int endExclusive) {
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}
//
public static IntStream stream(int[] array) {
return stream(array, 0, array.length);
}
public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
}
//
public static LongStream stream(long[] array) {
return stream(array, 0, array.length);
}
public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
}
//
public static DoubleStream stream(double[] array) {
return stream(array, 0, array.length);
}
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}
Collection:将各种继承Collection的接口(List, Set)转换为Stream
List stringList = new ArrayList<>();
Stream streamList = stringList.stream();
Set map = new HashSet<>();
Stream streamMap = map.stream();
Collection相关新加方法
java1.8后引入了接口的默认方法和静态方法,接口中也可以有实现方法了
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
除了以上可以获得Stream对象外,还有一些相应的方法:
先看一张结构图:
尝试从以上子类中获得相应的Stream:
IntStream intStream = IntStream.of(1, 2, 3);
OptionalDouble average = intStream.average();
System.out.println(average);//OptionalDouble[2.0]
LongStream longStream = LongStream.of(1000, 2000, 3000);
OptionalLong first = longStream.findFirst();
System.out.println(first);//OptionalLong[1000]
DoubleStream doubleStream = DoubleStream.of(1.0, 2.0, 3.0);
OptionalDouble max = doubleStream.max();
System.out.println(max);//OptionalDouble[3.0]
Stream streamString = Stream.of("a", "b", "c", "d");
long count = streamString.count();
System.out.println(count);//4
得到Stream后,我们便可对其进行一系列操作,以上只是实现了几个简单的方法。接下来我们来看看一些常用的操作
常用的流操作
先来看两个概念:惰性求值方法,及早求值方法。
先记住,只要是方法返回的是Stream对象,则是惰性求值方法,其它的是及早求值方法。
这样的设计, 为链式调用提供便利。一般的调用顺序为:
1.获得流 (of)
2.惰性求值(of, filter, sorted)
3.及早求值(collect)
List list = Stream.of("Java", "Android", "Php", "IOS")//获得Stream对象
.filter(s -> s.length() > 3)//过滤,只保留长度大于3的
.sorted()//排序
.collect(Collectors.toList());//将结果输出到List中
System.out.println(list);//[Android, Java]
以此分类,先来看几个惰性求值方法:
map:将一种类型转换为另一种类型
Stream map(Function super T, ? extends R> mapper);
Function stringStringFunction = s -> s.toUpperCase();
List list = Stream.of("Java", "Android", "Php", "IOS")
.map(stringStringFunction)
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[JAVA, ANDROID, PHP, IOS]
相当于:
List list = Stream.of("Java", "Android", "Php", "IOS")
.map(s -> s.toUpperCase())
//.map(String::toUpperCase)//或写成方法引用的格式,可以理解为以传入的参数为对象,调用该方法。
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[JAVA, ANDROID, PHP, IOS]
filter:过滤,保留符合参数条件的数据
Stream filter(Predicate super T> predicate);
List list = Stream.of("Java", "Android", "Php", "IOS")
.filter(s -> s.startsWith("A") | s.startsWith("I"))
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[Android, IOS]
flatMap:将多个Stream合并为一个Stream
Stream flatMap(Function super T, ? extends Stream extends R>> mapper);
List languageList = Arrays.asList("Java", "Android", "Php", "IOS");
List movieList = Arrays.asList("声之形", "你的名字", "千与千寻");
List list = Stream.of(languageList, movieList)
.flatMap(Collection::stream)//这里的参数为List
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[Java, Android, Php, IOS, 声之形, 你的名字, 千与千寻]
distinct:去重
Stream distinct();
List collect = Stream.of(1, 2, 3, 4, 3, 5, 4)
.distinct()
.collect(Collectors.toList());
System.out.println(collect);//[1, 2, 3, 4, 5]
limit:限制个数
Stream limit(long maxSize);
List collect = Stream.of(1, 2, 3, 4, 3, 5, 4)
.limit(5)
.distinct()
.collect(Collectors.toList());
System.out.println(collect);//[1, 2, 3, 4]
peek:用于调试
Stream peek(Consumer super T> action);
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
输出:
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
skip:跳过若干个数据
Stream skip(long n);
List collect = Stream.of(1, 2, 3, 4, 5, 6)
.skip(2)
.collect(Collectors.toList());
System.out.println(collect);//[3, 4, 5, 6]
再来看几个及早求值方法:
collect:从流中生成相应的集合
R collect(Collector super T, A, R> collector);
List list = Stream.of("Java", "Android", "Php", "IOS")
.filter(s -> s.length() > 3)
.sorted()
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[Android, Java]
Set set = Stream.of("Java", "Android", "Php", "IOS")
.filter(s -> s.length() > 3)
.sorted()
.collect(Collectors.toSet());
System.out.println(set.getClass().getSimpleName() + set);//HashSet[Java, Android]
Function keyMapper = s -> s + "key";
Function valueMapper = s -> s + "value";
Map map = Stream.of("Java", "Android", "Php", "IOS")
.filter(s -> s.length() > 3)
.sorted()
.collect(Collectors.toMap(keyMapper, valueMapper));
System.out.println(map.getClass().getSimpleName() + map);//HashMap{Javakey=Javavalue, Androidkey=Androidvalue}
max/min: 按照一定规则,获得最大,最小值
Optional max(Comparator super T> comparator);
Optional max = Stream.of("Java", "Android", "Php", "IOS")
.max(Comparator.comparing(String::length));
System.out.println(max.get());//Android
count: 获得数据的个数
long count();
long count = Stream.of("Java", "Android", "Php", "IOS").count();
System.out.println(count);//4
reduce: 从一组值中生成一个值 (以上的max, min, count都是reduce操作)
T reduce(T identity, BinaryOperator accumulator);
Integer reduce = Stream.of(1, 2, 3, 4, 5).reduce(0, (first, second) -> first + second);
System.out.println(reduce);//15
forEach:遍历输出
void forEach(Consumer super T> action);
Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);
未完待续。。。