在Java 8中API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。在Java中只要你应用的版本是java 8以上的话都能使用该API,但是在Android中如果API低于24时,是无法使用该java API,今天我们来介绍在Android中如何使用 Stream ,还有常用的操作符。
在操作之前我们来认识一下什么是Stream? 有什么特性呢? 进入 Sream API
上文已经提及了在默认的Android API中只要在API 24以上才能使用如下:
@RequiresApi(api = Build.VERSION_CODES.N) //必须标志在Android N才能使用,也就是API>=24才能使用 public void testStream() { List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); Stream.of(strings).filter(s -> !strings.isEmpty()).forEach(System.out::println); }
但是为了使用Stream的话,我们可以引用Stream依赖
//在Project build.gradle中添加 allprojects { repositories { //... maven { url 'https://jitpack.io' } } } //在Module app build.gradle 中添加 implementation 'com.annimon:stream:1.2.1'
java.util.stream.Stream
,而依赖库的包是 com.annimon.stream.Stream
,这里需要大家在使用的时候注意。 我们先来一个简单的例子
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); //输出list的元素 Stream.of(strings).forEach(System.out::println);
当然了,熟悉lambda表达式的同学肯定觉得这有什么好的呢?List也直接可以输出而且很方便呢?如下:
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); strings.forEach(System.out::println);
上面两个例子并没有让我们觉得Stream很牛逼是吧,不急,我们继续进行看看,Stream是不是很强大。
返回其元素为指定值的顺序有序流。
Stream<Integer> stream = Stream.of(1, 2, 3, 4); System.out.println(stream.count()); //stream.count():返回此流中元素的数量。 输出: 4
返回一个流,该流包含将给定函数应用于此流的元素的结果
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); //将字符串转换为int输出 Stream.of(strings).map(Integer::parseInt).forEach(System.out::println); 输出: 1 2 2 3 4
返回一个IntStream,它包含将给定函数应用于此流的元素的结果。
相同的还有mapToLong、mapToDouble
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); Stream.of(strings).mapToInt(Integer::parseInt).forEach(System.out::println); 输出: 1 2 2 3 4
返回一个流,该流包含将此流的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容的结果。
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); List<String> strings1 = Arrays.asList("a", "b", "c"); Stream.of(strings,strings1).flatMap(Stream::of).forEach(System.out::println); 输出: 1 2 2 3 4 a b c
返回由与此给定谓词匹配的此流的元素组成的流。过滤器,如下下面例子过滤空字符串
List<String> strings = Arrays.asList("1", "2", "2", "", "3", "4"); Stream.of(strings).filter(s -> !s.isEmpty()).map(Integer::parseInt).forEach(System.out::println); 输出: 1 2 2 3 4
去除List重复的元素,返回由此流的不同元素(根据Object.equals(Object))组成的流。
List<String> strings = Arrays.asList("1", "2", "2", "", "3", "4"); Stream.of(strings).filter(s -> !s.isEmpty()).distinct().map(Integer::parseInt).forEach(System.out::println); 输出: 1 2 3 4
返回由此流的元素组成的流,截断为长度不超过maxSize。如下maxSize=3时。
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); Stream.of(strings).limit(3).forEach(System.out::println); 输出: 1 2 2
在丢弃流的前n个元素后,返回由此流的其余元素组成的流。如下n=3,则丢弃前面3个元素。
List<String> strings = Arrays.asList("1", "2", "2", "3", "4"); Stream.of(strings).skip(3).limit(3).forEach(System.out::println); 输出: 3 4
返回由此流的元素组成的流,按照自然顺序排序。默认为升序
List<String> strings = Arrays.asList("1", "5", "2", "6", "4"); Stream.of(strings).sorted().forEach(System.out::println); 输出: 1 2 4 5 6
返回此流的所有元素是否与提供的断言匹配。boolean值
List<String> strings = Arrays.asList("1", "5", "2", "6", "4"); System.out.println(Stream.of(strings).allMatch(s -> strings.contains("a"))); 输出: false System.out.println(Stream.of(strings).allMatch(s->strings.contains("1"))); 输出: true
返回此流的任何元素是否与提供的断言匹配。
List<String> strings = Arrays.asList("1", "5", "2", "6", "4"); System.out.println(Stream.of(strings).anyMatch(s -> s.contains("1"))); 输出: true
Stream 中没有一个元素符合传入的 断言
List<String> strings = Arrays.asList("1", "5", "", "6", "4"); System.out.println(Stream.of(strings).noneMatch(s -> s.contains("8"))); 输出: true
输出为一个新的集合数据。
List<String> strings = Arrays.asList("1", "5", "", "6", "4"); List<String> strings1 = Stream.of(strings).filter(s -> !s.isEmpty()).collect(Collectors.toList()); strings1.forEach(System.out::println); 输出: 1 5 6 4 List<String> string = Arrays.asList("1", "5", "6", "6", "4"); Stream.of(string).filter(s -> !s.isEmpty()).collect(Collectors.toSet()).forEach(System.out::println);//Collectors.toSet() 不能出现重复元素,并进行排序输出。hashSet类似,但是Collectors.toSet()会进行排序 输出: 1 4 5 6
创建一个延迟连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。
List<String> strings = Arrays.asList("1", "5", "", "6", "4"); Stream strings1 = Stream.of(strings).filter(s -> !s.isEmpty()); List<String> string = Arrays.asList("8", "5", "6", "6", "4"); Stream strings2 = Stream.of(string).filter(s -> !s.isEmpty()); Stream.concat(strings1, strings2).forEach(System.out::println); 输出: 1 5 6 4 8 5 6 6 4
使用关联累加函数对此流的元素执行减少,并返回描述减少值的Optional(如果有)。
int sum = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get(); System.out.println(sumValue1); int sum1 = Stream.of(1, 2, 3, 4).reduce(2, Integer::sum);//表示identity=2,即该sum的初始值,所以Stream中的总和等于2+(1+2+3+4)=12 System.out.println(sumValue); 输出: 10 12
输出Stream流的和、最大值、最小值,返回的是 Optional
System.out.println(Stream.of(1, 2, 3, 4).reduce(Integer::sum).get()); List<Integer> num = Arrays.asList(1, 3, 8, 5); System.out.println(Stream.of(num).reduce(Integer::max).get()); System.out.println(Stream.of(num).reduce(Integer::min).get()); 输出: 10 8 1
返回一个空的顺序Stream。
Stream<Integer> stream = Stream.of(1, 2, 3, 4); Stream<Integer> stream1 = stream.empty(); System.out.println(stream1.count()); 输出: 0
返回描述此流的第一个元素的Optional,如果流为空,则返回空Optional。
Stream<Integer> stream = Stream.of(1, 2, 3, 4); System.out.println(stream.findFirst().get()); 输出: 1
返回由此流的元素组成的流,另外在每个元素上执行提供的操作,因为元素是从结果流中消耗的。
Stream<String> stream = Stream.of("a", "c", "C", "f"); List<String> list = stream.peek(e -> System.out.println("value: " + e)).map(String::toUpperCase).collect(Collectors.toList()); list.forEach(System.out::println); 输出: value: a value: c value: C value: f A C C F
Object[] array = Stream.of(1, 2, 3, 4).toArray(); Integer[] n = Stream.of(1, 2, 4, 5, 7, 3, 11).skip(3).toArray(Integer[]::new); Stream.of(n).forEach(System.out::println); 输出: 5 7 3 11
案例下载
Stream 常用的操作符,我们在这里的案例都差别多测试了,是不是感觉 Stream 给我们的感觉是一种很棒的开发案例,我们可以在开发中使用它,这样方便我们对集合的操作。
可能有些同学看到第一个的时候就觉得在哪里见过?是的,没错,是不是和 RxJava 的操作符的作用差不多都是非常类似的。当然了, RxJava 的操作是非常丰富的,希望大家可以多多去了解。