Java8 lambda详解 stream

一、stream的 初始化

1、从 Collection 和数组

//值
Stream<String> stream = Stream.of("chaimm","peter","john");
//数组
//Arrays.stream(T array) or Stream.of();
String[] names = {"chaimm","peter","john"};
Stream<String> stream = Arrays.stream(names);
Stream<String> stream = Stream.of(names);
//集合
//Collection.stream()
//Collection.parallelStream()
List<Person> list = new ArrayList<Person>(); 
Stream<Person> stream = list.stream();//串行流
Stream<Person> stream = list.parallelStream();//并行流
//concat将两个流链接在一起,返回一个新的stream
Stream.concat(stream ,stream );

2、从 BufferedReader
java.io.BufferedReader.lines()

String filePth = "C:/Users/admin1/Desktop/guowang/2017-12-09.txt";
//lines方法里就是用的bufferedReader.lines
Stream<String> lines = Files.lines(Paths.get(filePth),Charset.defaultCharset());
lines.forEach(System.out::println);

3、静态工厂
java.util.stream.IntStream.range()
java.nio.file.Files.walk()
4、自己构建
java.util.Spliterator
5、其它
Random.ints()
BitSet.stream()
Pattern.splitAsStream(java.lang.CharSequence)
JarFile.stream()
6、无限流的创建
generate的方法接受一个无参数的函数,
Stream.generate(Math::random);

二、流的操作分为两种

1、intermediate (中间操作):一个流可以有一个或多个中间操作。中间操作对数据进行过滤/映射,同时返回一个新的stream,以供后续操作。中间操作都是惰性化(lazy)的,单独运行中间操作代码是没有任何效果的,只有在调用终止操作的时候才会一起执行中间操作。
2、Terminal(终止操作):一个流只有一个终止操作,流一旦被使用后就没有了。终止操作的运行才真正的开始流的遍历,返回一个结果。
Intermediate
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、unordered、 peek、 limit、 skip、 parallel、 sequential
Terminal
forEach、 forEachOrdered、 toArray、collect、 reduce、 min、 max、 count、sum、average 、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterate
Short-circuiting
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

package model;

public class Person {
	private String name;
	private int age;
	private boolean isStudent;

	public Person() {

	}

	public Person(String name, int age, boolean isStudent) {
		this.name = name;
		this.age = age;
		this.isStudent = isStudent;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public boolean isStudent() {
		return isStudent;
	}

	public void setStudent(boolean isStudent) {
		this.isStudent = isStudent;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", isStudent=" + isStudent + "]";
	}

}

map/flatMap
映射:把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素。

@Test
public void test1() {
	List<Person> perList = Arrays.asList(
				new Person("张三", 16, true), 
				new Person("李四", 17, false), 
				new Person("王五", 17, false)
				);
	perList.stream().map((person) -> (person.getName())).forEach(System.out::println);
	perList.stream().mapToInt((person) -> (person.getAge())).forEach(System.out::println);
}
@Test
public void test3() {
	//将底层元素合并成一个集合
	//[[1],[2,3],[456]]->[1,2,3,4,5,6]
	List<List<Integer>> list =Arrays.asList(
				Arrays.asList(1), 
				Arrays.asList(2, 3), 
				Arrays.asList(4, 5, 6)
				);
	//集合输出为[1, 2, 3, 4, 5, 6]
	List<Integer> collect = list.stream().flatMap((childList) -> childList.stream()).collect(Collectors.toList());
}

filter
过滤:满足条件的元素保留组成一个新的stream

@Test
public void test4() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	//年龄大于16的人
	perList.stream().filter(person->person.getAge()>16).forEach(System.out::println);
}

distinct
去重:调用equals方法比较是否相同,相同则保留一个

@Test
public void test5() throws IOException {
		List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	perList.stream().mapToInt((person) -> (person.getAge())).forEach(System.out::println);
	//去除相同年龄的
	perList.stream().mapToInt((person) -> (person.getAge())).distinct().forEach(System.out::println);
}

sorted/unordered
排序:sorted()默认排序,sorted(Comparator comparator)自定义排序规则
unordered:无序的

@Test
public void test5() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	//按年龄排序
	perList.stream().sorted((p1,p2) -> (Integer.compare(p1.getAge(), p2.getAge()))).forEach(System.out::println);
}

peek
用来打印中间信息,记录log日志
遍历时对符合条件的元素进行处理,下面例子将一个集合根据不同条件拆分成两个集合,感觉这样类似于for循环对数据处理

@Test
public void test6() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	List<Person> perList1 = new ArrayList<>();
	List<Person> perList2 = new ArrayList<>();
	perList.stream().peek(e -> {
			if (e.getAge() > 16) {
				perList1.add(e);
			}
			if(e.isStudent()) {
				perList2.add(e);
			}
		}).forEach(x->{});
	System.out.println(perList1);
	System.out.println(perList2);
}

limit/skip
limit:返回 Stream 的前面 n 个元素
skip:略过前 n 个元素

@Test
public void test7() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	perList.stream().limit(1).forEach(System.out::println);
	System.out.println("---------------------------------");
	perList.stream().skip(2).forEach(System.out::println);
}

parallel/sequential
parallel:设置为并行流
sequential:设置为串行流
forEach/forEachOrdered
forEach和forEachOrdered主要区别:在并行处理,当处理并行流时,forEach的执行顺序是随机的,而forEachOrdered是按顺序执行的。所以forEach的效率会更高

@Test
public void test8() throws IOException {
	Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s));
	//输出的顺序永远都是 AAA BBB CCC
	Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s));
}

toArray/collect
toArray:转成数组
collect:转成集合类型使用Collectors可以转成任意集合,以下是常用集合类

@Test
public void test9() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	Object[] arrays = perList.stream().toArray();
	System.out.println(arrays);
	Map<String, Person> map = perList.stream().collect(Collectors.toMap((x) -> (x.getName()), (y) -> (y)));
	System.out.println(map);
	List<Person> list = perList.stream().collect(Collectors.toList());
	System.out.println(list);
	Set<Person> set = perList.stream().collect(Collectors.toSet());
	System.out.println(set);
	//输出String并使用分割符进行分割
	String names = perList.stream().map(Person::getName).collect(Collectors.joining(",", "<", ">"));
	System.out.println(names);
	//将stream按boolean分成两个保存在map中
	Map<Boolean, List<Person>> perMap = perList.stream().collect(Collectors.partitioningBy(Person::isStudent));
	perMap.forEach((key, value) -> (System.out.println(key + "---" + value.toString())));
	//将stream按group进行分组
	Map<Integer, List<Person>> perMap2 = perList.stream().collect(Collectors.groupingBy(Person::getAge));
	perMap2.forEach((key, value) -> (System.out.println(key + "---" + value.toString())));
	//根据自己的条件进行分组
	Map<Integer, List<Person>> perMap2 = perList.stream().collect(Collectors.groupingBy((person) -> {
		if(person.getAge() > 16) {
			return 1;
		} else {
			return 2;
		}
	}));
    perMap2.forEach((key, value) -> System.out.println(key + "---" + value.toString()));
	//将stream按group进行分组,并统计数量
	Map<Integer, Long> count = perList.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
	count.forEach((key, value) -> (System.out.println(key + "---" + value.toString())));
	//将stream按group进行分组,并获取名字集合
	Map<Integer, List<String>> names2 = perList.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList())));
	names2.forEach((key, value) -> (System.out.println(key + "---" + value.toString())));
}

reduce/min/max/count/sum/average
归约:主要作用是把 Stream 元素组合起来。字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce
下面需要注意的是如果没有初始值,返回内容会用optionnal封装
StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,可以使用summaryStatistics进行max,min,avg,count,sum的统计

@Test
public void test10() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	String name = perList.stream().map(person -> person.getName()).reduce("", (p1, p2) -> (p1.concat(p2)));
	Optional<String> nameOp = perList.stream().map(person -> person.getName()).reduce((p1, p2) -> (p1.concat(p2)));
	System.out.println(name);
		Integer age = perList.stream().map(person -> person.getAge()).reduce(0, (p1, p2) -> (p1 + p2));
	Optional<Integer> ageOp = perList.stream().map(person -> person.getAge()).reduce((p1, p2) -> (p1 + p2));
	System.out.println(age);
	IntSummaryStatistics intSummary = perList.stream().mapToInt(person -> person.getAge()).summaryStatistics();
	intSummary.getAverage();
	intSummary.getMax();
	intSummary.getMin();
	intSummary.getSum();
	intSummary.getCount();
}

allMatch/anyMatch/noneMatch
Stream 有三个 match 方法,从语义上说:
allMatch:Stream 中全部元素符合传入的 predicate,返回 true
anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true

@Test
public void test11() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	boolean isAllAdult = perList.stream().allMatch(p -> p.getAge() > 18);
	System.out.println(isAllAdult);
	boolean isThereAnyChild = perList.stream().anyMatch(p -> p.getAge() < 12);
	System.out.println( isThereAnyChild);
}

findFirst/findAny
findFirst:总是返回 Stream 的第一个元素,或者空。
findAny:返回任意一个,或者空。

@Test
public void test12() throws IOException {
	List<Person> perList = Arrays.asList(new Person("张三", 16, true), new Person("李四", 17, false), new Person("王五", 17, false));
	Optional<Person> person = perList.stream().findFirst();
	System.out.println(person.get());
	Optional<Person> person2 = perList.stream().findAny();
	System.out.println(person2);
}

iterate
iterate 跟 reduce 操作很像,接受一个种子值,和一个 UnaryOperator(例如 f)。然后种子值成为 Stream 的第一个元素,f(seed) 为第二个,f(f(seed)) 第三个,以此类推。

@Test
public void test13() throws IOException {
	Stream.iterate(0, n -> n + 3).limit(10).forEach(x -> System.out.print(x + " "));
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值