中级11 - Java 8 Sream
2020-06-02 本文已影响0人
晓风残月1994
1. 创建 Stream
- Collection.stream
- Stream.of
- String.chars
- IntStream.range
2. Stream 中间操作
返回 stream 的操作都是中间操作。
collect 等
- 仍然返回 Stream 的操作
- filter
- map
- flatMap 每使用一次,流降低一个维度
- sorted
3. Stream 终结操作
- 返回非 stream 的操作,包括返回 void
- 一个流只能被消费一次
- collect【最强大的操作】
- forEach
- count/max/min
- findFirst/findAny
- anyMatch/noneMatch
4. Collector 与 Collectors
Collector 接口顾名思义收集者,把输入流汇聚到一起成为一个 collection 集合。而 Collectors 则是对应的工具类。
一般配合 stream.collect 使用。Collectors 常用方法:
- toSet/toList/toCollection
- joining
- toMap
- groupingBy
5. 并发流
parallel 并发数是CPU核心数-1,当前CPU核心数是:Runtime.getRuntime().availableProcessors()。
- parallelStream()
- 可以通过并发提高互相独立的操作的性能
- 在正确使用的前提下,可以获得近似线性的性能提升
- 但是需要进行实际测试,盲目的使用可能导致实际上更慢
6. 实战
6.1 filter/count/sorted/map/toCollection
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
public class Problem1 {
static class User {
private String name;
private int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
// 编写一个方法,统计"年龄大于等于60的用户中,名字是两个字的用户数量"
public static int countUsers(List<User> users) {
return (int) users.stream()
.filter(user -> user.getAge() >= 60)
.filter(user -> user.getName().length() == 2)
.count();
}
// 编写一个方法,筛选出年龄大于等于60的用户,然后将他们按照年龄从大到小排序,将他们的名字放在一个LinkedList中返回
public static LinkedList<String> collectNames(List<User> users) {
return users.stream()
.filter(user -> user.getAge() >= 60)
.sorted(Comparator.comparing(User::getAge).reversed())
.map(User::getName)
.collect(Collectors.toCollection(LinkedList::new));
}
public static void main(String[] args) {
System.out.println(
countUsers(
Arrays.asList(
new User("张三", 60),
new User("李四", 61),
new User("张三丰", 300),
new User("王五", 12))));
System.out.println(
collectNames(
Arrays.asList(
new User("张三", 60),
new User("李四", 61),
new User("张三丰", 300),
new User("王五", 12))));
}
}
6.2 anyMatch
import java.util.Arrays;
import java.util.List;
public class Problem2 {
// 判断一段文本中是否包含关键词列表中的文本,如果包含任意一个关键词,返回true,否则返回false
// 例如,text="catcatcat,boyboyboy", keywords=["boy", "girl"],返回true
// 例如,text="I am a boy", keywords=["cat", "dog"],返回false
public static boolean containsKeyword(String text, List<String> keywords) {
// return keywords.stream().filter(text::contains).findAny().isPresent(); // 笨办法
return keywords.stream().anyMatch(text::contains);
}
public static void main(String[] args) {
System.out.println(containsKeyword("catcatcat,boyboyboy", Arrays.asList("boy", "girl")));
System.out.println(containsKeyword("I am a boy", Arrays.asList("cat", "dog")));
}
}
6.3 String.chars/filter/count
public class Problem3 {
// 使用流的方法,再把之前的题目做一遍吧
// 统计一个给定的字符串中,大写英文字母(A,B,C,...,Z)出现的次数。
// 例如,给定字符串"AaBbCc1234ABC",返回6,因为该字符串中出现了6次大写英文字母ABCABC
public static int countUpperCaseLetters(String str) {
return (int) str.chars().filter(Character::isUpperCase).count();
}
public static void main(String[] args) {
System.out.println(countUpperCaseLetters("AaBbCc1234ABC"));
}
}
6.4 orted/groupingBy
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class Problem4 {
// 再用流的方法把之前的题目做一遍吧:
// 请编写一个方法,对传入的List<Employee>进行如下处理:
// 返回一个从部门名到这个部门的所有用户的映射。同一个部门的用户按照年龄进行从小到大排序。
// 例如,传入的employees是[{name=张三, department=技术部, age=40 }, {name=李四, department=技术部, age=30 },
// {name=王五, department=市场部, age=40 }]
// 返回如下映射:
// 技术部 -> [{name=李四, department=技术部, age=30 }, {name=张三, department=技术部, age=40 }]
// 市场部 -> [{name=王五, department=市场部, age=40 }]
public static Map<String, List<Employee>> collect(List<Employee> employees) {
return employees.stream()
.sorted(Comparator.comparing(Employee::getAge))
.collect(Collectors.groupingBy(Employee::getDepartment));
}
public static void main(String[] args) {
System.out.println(
collect(
Arrays.asList(
new Employee(1, "张三", 40, "技术部"),
new Employee(2, "李四", 30, "技术部"),
new Employee(3, "王五", 40, "市场部"))));
}
static class Employee {
// 用户的id
private final Integer id;
// 用户的姓名
private final String name;
// 用户的年龄
private final int age;
// 用户的部门,例如"技术部"/"市场部"
private final String department;
Employee(Integer id, String name, int age, String department) {
this.id = id;
this.name = name;
this.age = age;
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", department='" + department + '\'' +
'}';
}
public Integer getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
public String getDepartment() { return department; }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Employee person = (Employee) o;
return Objects.equals(id, person.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
}
6.5 toMap
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Problem5 {
// 使用流的方法,把订单处理成ID->订单的映射
// 例如,传入参数[{id=1,name='肥皂'},{id=2,name='牙刷'}]
// 返回一个映射{1->Order(1,'肥皂'),2->Order(2,'牙刷')}
public static Map<Integer, Order> toMap(List<Order> orders) {
return orders.stream()
.collect(Collectors.toMap(Order::getId, order -> order));
}
public static void main(String[] args) {
System.out.println(toMap(Arrays.asList(new Order(1, "肥皂"), new Order(2, "牙刷"))));
}
static class Order {
private Integer id;
private String name;
Order(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() { return id; }
public String getName() { return name; }
@Override
public String toString() {
return "Order{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
}
6.6 filter/joining
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class Problem6 {
// 使用流的方法,把所有长度等于1的单词挑出来,然后用逗号连接起来
// 例如,传入参数words=['a','bb','ccc','d','e']
// 返回字符串a,d,e
public static String filterThenConcat(Set<String> words) {
return words.stream()
.filter(word -> word.length() == 1)
.collect(Collectors.joining(","));
}
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>(Arrays.asList("a", "bb", "ccc", "d", "e"));
System.out.println(filterThenConcat(set));
}
}
7. 参考
- Effective Java Item 42-48
- IDEA stream 调试器