参考书籍: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<Integer> tConsumer = (Integer x) -> System.out.println(x);
Consumer<Double> doubleConsumer = (Double d) -> System.out.println(d);
//由方法引用代替
Consumer<Integer> tConsumer1 = System.out::println;
Consumer<Double> doubleConsumer1 = System.out::println;
tConsumer.accept(10);
tConsumer1.accept(101);
doubleConsumer.accept(20.0);
doubleConsumer1.accept(201.0);
Predicate<Integer> 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<Integer> 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<String> stream = Arrays.stream(arrays);
相关新加方法及重载方法:
//
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public static <T> Stream<T> 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<String> stringList = new ArrayList<>();
Stream<String> streamList = stringList.stream();
Set<Long> map = new HashSet<>();
Stream<Long> streamMap = map.stream();
Collection相关新加方法
java1.8后引入了接口的默认方法和静态方法,接口中也可以有实现方法了
default Stream<E> 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<String> 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<String> 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:将一种类型转换为另一种类型
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Function<String, String> stringStringFunction = s -> s.toUpperCase();
List<String> 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<String> 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<T> filter(Predicate<? super T> predicate);
List<String> 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
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
List<String> languageList = Arrays.asList("Java", "Android", "Php", "IOS");
List<String> movieList = Arrays.asList("声之形", "你的名字", "千与千寻");
List<String> list = Stream.of(languageList, movieList)
.flatMap(Collection::stream)//这里的参数为List<String>
.collect(Collectors.toList());
System.out.println(list.getClass().getSimpleName() + list);//ArrayList[Java, Android, Php, IOS, 声之形, 你的名字, 千与千寻]
distinct:去重
Stream<T> distinct();
List<Integer> 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<T> limit(long maxSize);
List<Integer> 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<T> 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<T> skip(long n);
List<Integer> collect = Stream.of(1, 2, 3, 4, 5, 6)
.skip(2)
.collect(Collectors.toList());
System.out.println(collect);//[3, 4, 5, 6]
再来看几个及早求值方法:
collect:从流中生成相应的集合
<R, A> R collect(Collector<? super T, A, R> collector);
List<String> 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<String> 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<String, String> keyMapper = s -> s + "key";
Function<String, String> valueMapper = s -> s + "value";
Map<String, String> 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<T> max(Comparator<? super T> comparator);
Optional<String> 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<T> 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);
未完待续。。。