目录
Java8 中的的stream非常好用,大部分的集合操作都可以实现。关于Stream的文章很多。这里只简单介绍一点调用问题。以便更好的理解Stream
一大堆初始化函数。
基本上任意类型的数据,均可找到相应的方法转到Steam
Collection<String> collection = Arrays.asList("a", "b", "c");
Stream<String> streamOfCollection = collection.stream();
Stream<String> streamOfArray = Stream.of("a", "b", "c");
Stream<String> streamOfArrayFull = Arrays.stream(arr);
Stream<String> streamOfArrayPart = Arrays.stream(arr, 1, 3);
Stream<String> streamBuilder = Stream.<String> builder().add("a").add("b").add("c").build();
Stream<String> streamGenerated = Stream.generate(() -> "element").limit(10);
Stream<Integer> streamIterated = Stream.iterate(40, n -> n + 2).limit(20);
IntStream intStream = IntStream.range(1, 3);
LongStream longStream = LongStream.rangeClosed(1, 3);
Random random = new Random();
DoubleStream doubleStream = random.doubles(3);
IntStream streamOfChars = "abc".chars();
Stream<String> streamOfString = Pattern.compile(", ").splitAsStream("a, b, c");
Path path = Paths.get("C:\\file.txt");
Stream<String> streamOfStrings = Files.lines(path);
Stream<String> streamWithCharset = Files.lines(path, Charset.forName("UTF-8"));
我们实例化一个Stream,中间操作可以一直进行,直到遇到终止函数。而且每个Stream只能有一个终止操作,中间操作可以有若干个。终止函数将返回一个已经被修改的Stream。
List<String> list =
Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck")
.filter(v->v.length() == 3)
.sorted()
.collect(Collectors.toList());
filter和sorted都是中间操作。而collect就是终止操作。此段代码会返回名称长度为3,并且会对这个数据进行排序后输出转换为List操作。
如果还有其他的中间操作。比如根据条件再次过滤。比如将每个字符串加上一个特殊字符等中间操作,都可以加在终止函数之前。
其他有关Stream的操作文档请自行搜索学习。
Stream中间操作为懒调用
所有的Stream中间操作,都是懒调用。意思是终止函数之前的函数,会根据最后的终止函数而决定是否被调用。
例如下代码:我们增加一个计数器counter
List<String> list = Arrays.asList("abc1", "abc2", "abc3");
AtomicInteger counter = new AtomicInteger(0);
Stream<String> stream = list.stream().filter(element -> {
counter.addAndGet(1);
return element.contains("2");
});
System.out.println(counter.get());
好像这个counter最终结果应该是3,实际结果:由于没有终止操作函数。这个计数器最后输出为0
意思是,根本filer这个函数就没有运行。但是我们加上一个终止函数,比如findFirst()
List<String> list = Arrays.asList("abc1", "abc2", "abc3");
AtomicInteger counter = new AtomicInteger(0);
Optional<String> v = list.stream().filter(element -> {
counter.addAndGet(1);
return element.contains("2");
}).findFirst();
System.out.println(counter.get());
此时counter的最终输出结果是 2,为什么?继续往下看
再来看下面的例子:
List<String> list = Arrays.asList("abc1", "abc2", "abc3");
Optional<String> stream = list.stream().filter(element -> {
System.out.println("filter() was called");
return element.contains("2");
}).map(element -> {
System.out.println("map() was called");
return element.toUpperCase();
}).findFirst();
输出结果是:
filter() was called
filter() was called
map() was called
filter被调用了2次,map被调用了一次。是因为findFirst终止操作只需要一个结果。而filter的第一个不满足条件,就继续判断第二个数据。发现符合filter条件。就不再判断后边的数据。而由于结果findFirst只需要一个结果。所以map操作只运行一次就不再继续。
如果有兴趣,请实验以下代码结果,并验证是否和自己想想的结果一样?
List<String> list = Arrays.asList("abc1", "abc2", "abc3");
AtomicInteger counter = new AtomicInteger(0);
long size = list.stream().map(element -> {
counter.addAndGet(1);
return element.substring(0, 3);
}).skip(2).count();
System.out.println(size);
System.out.println(counter.get());
Java9提供了新的函数takeWhile
类似于for循环的break及时终止Stream
Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck")
.takeWhile(n -> n.length() % 2 != 0)
.forEach(System.out::println);
如果我们运行以上代码,得到的结果是:
cat
dog
相比较下,使用for循环的代码,应该是:
//java9 中才有List.of
List<String> list = List.of("cat", "dog", "elephant", "fox", "rabbit", "duck");
for (String item : list)
{
if (item.length() % 2 == 0)
{
break;
}
System.out.println(item);
}
本程序所有源码见:java stream 初始化及懒调用源代码https://download.csdn.net/download/2301_77345366/87666186