/**
* @author yigen shi
* @Description <p>不存贮数据</p>
* <p>不改变数据源</p>
* <p>延迟执行</p>
* <p>只能消费一次</p>
* @date 2019/7/1 19:35
*/
public class StreamTest {
private String[] arr1 = {"abc", "a", "bc", "abcd"};
private static class User {
private Long id;
private String name;
private Integer score;
public User(String name, Integer score) {
this.name = name;
this.score = score;
}
public User(Long id, String name, Integer score) {
this.id = id;
this.name = name;
this.score = score;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public void say() {
System.out.println("hello world");
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
private List<User> userList = new ArrayList<User>() {
{
add(new User(1L, "aa", 80));
add(new User(2L, "bb", 85));
add(new User(3L, "cc", 90));
add(new User(4L, "aa", 95));
}
};
/*------------------------流的特性开始----------------------------*/
/**
* Stream操作不改变数据源
*/
@Test
public void testUnChangeDataSource() {
List<String> list = Lists.newArrayList("aa", "bb", "cc");
List<String> filters = list.stream()
.filter("aa"::equals)
.collect(Collectors.toList());
System.out.println(filters); // [aa]
System.out.println(list); // [aa, bb, cc]
}
/**
* 测试stream的延迟执行 如果stream是立即执行的话,会先打印filter方法里面的begin compare
*/
@Test
public void testDelay() {
Stream<User> stream = userList.stream().filter(student -> {
student.say();
return true;
}).limit(10);
System.out.println("split-------------------------------------");
List<User> studentList = stream.collect(Collectors.toList());
System.out.println(studentList);
}
/**
* 测试stream流的只能一次消费
*/
@Test(expected = Exception.class)
public void testConsumeOnlyOnce() {
Stream<String> stream = Stream.generate(() -> "user").limit(20);
stream.forEach(System.out::println);
stream.forEach(System.out::println);
}
/*------------------------流的特性结束----------------------------*/
/*------------------------流的创建开始----------------------------*/
/**
* 通过数组创建流
*/
@Test
public void testArrayStream() {
//1.通过Arrays.stream
//1.1基本类型
int[] arr = new int[]{1, 2, 34, 5};
IntStream intStream = Arrays.stream(arr);
long[] lrr = new long[]{1, 2, 3, 4};
LongStream longStream = Arrays.stream(lrr);
//1.2引用类型
User[] studentArr = new User[]{new User("s1", 29), new User("s2", 27)};
Stream<User> studentStream = Arrays.stream(studentArr);
//2.通过Stream.of
Stream<Integer> stream1 = Stream.of(1, 2, 34, 5, 65);
//注意生成的是int[]的流
Stream<int[]> stream2 = Stream.of(arr, arr);
stream2.forEach(System.out::println);
}
/**
* 通过集合创建流
*/
@Test
public void testCollectionStream() {
// 通过List创建流
List<String> list = Arrays.asList("11212", "dfd", "2323", "dfhgf");
Stream<String> listStream = list.stream();
// 通过Set创建流
HashSet<String> set = new HashSet<>(list);
Stream<String> setStream = set.parallelStream();
// 通过队列创建流
Queue<String> queue = new ArrayDeque<>();
Stream<String> queueStream = queue.stream();
// 通过栈创建流
Stack<String> stack = new Stack<>();
Stream<String> stackStream = stack.stream();
// 通过Vector创建流
Vector<String> vector = new Vector<>();
Stream<String> vectorStream = vector.stream();
}
@Test
public void testParallelStream() {
List<String> strs = Arrays.asList("11212", "dfd", "2323", "dfhgf");
// 创建串行流(普通流)
Stream<String> stream = strs.stream();
// 创建并行流
Stream<String> stringStream = strs.parallelStream();
}
/**
* 创建空的流
*/
@Test
public void testEmptyStream() {
//创建一个空的stream
Stream<Integer> stream = Stream.empty();
}
/**
* 创建无限流
*/
@Test
public void testUnlimitStream() {
//创建无限流,通过limit提取指定大小
Stream.generate(() -> "number" + new Random().nextInt()).limit(100)
.forEach(System.out::println);
Stream.generate(() -> new User("name", 10)).limit(20).forEach(System.out::println);
}
/**
* 产生规律的数据
*/
@Test
public void testUnLimitStream1() {
Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::println);
Stream.iterate(0, x -> x).limit(10).forEach(System.out::println);
//Stream.iterate(0,x->x).limit(10).forEach(System.out::println);与如下代码意思是一样的
Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
}
/*------------------------流的创建结束----------------------------*/
/*------------------------流的操作开始----------------------------*/
/**
* 过滤 列出班上超过85分的学生姓名,并按照分数降序输出用户名字
*/
@Test
public void testFilter() {
List<String> studentList = userList.stream()
.filter(x -> x.getScore() > 85)
.sorted(Comparator.comparing(User::getScore).reversed())
.map(User::getName)
.collect(Collectors.toList());
System.out.println(studentList);
}
/**
* 分组
*/
@Test
public void testGroupBy() {
// 根据分数分组
Map<Integer, List<User>> map = userList.stream()
.filter(x -> x.getScore() > 85)
.collect(Collectors.groupingBy(User::getScore));
System.out.println(map);
// 根据名字分组
Map<String, List<User>> nameMap = userList.stream()
.collect(Collectors.groupingBy(User::getName));
System.out.println(nameMap);
}
/**
* 去重操作
*/
@Test
public void testDistinct() {
List<Integer> list = Lists.newArrayList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6);
List<Integer> result = list.stream().distinct().collect(Collectors.toList());
System.out.println(result);
}
/*--------------------stream的操作 ----------------------*/
/**
* map:转换流,将一种类型的流转换为另外一种流 map把一种类型的流转换为另外一种类型的流 将String数组中字母转换为小写
*/
@Test
public void testMap() {
String[] arr = new String[]{"yes", "YES", "no", "NO"};
Arrays.stream(arr).map(String::toLowerCase).forEach(System.out::println);
}
/**
* filter:过滤流,过滤流中的元素
*/
@Test
public void testFilter01() {
Integer[] arr = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Arrays.stream(arr).filter(x -> x > 3 && x < 8).forEach(System.out::println);
Arrays.stream(arr).filter(x -> x > 3)
.filter(x -> x < 8).forEach(System.out::println);
}
private static class SysUser {
private Long id;
private String name;
private String description;
private List<SysRole> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<SysRole> getRoles() {
return roles;
}
public void setRoles(List<SysRole> roles) {
this.roles = roles;
}
}
private static class SysRole {
private Long id;
private String name;
private String description;
private List<SysPermission> permissions;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<SysPermission> getPermissions() {
return permissions;
}
public void setPermissions(List<SysPermission> permissions) {
this.permissions = permissions;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private static class SysPermission {
private Long id;
private String name;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "SysPermission{" +
"id=" + id +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}
/**
* flapMap:拆解流
*/
@Test
public void testFlapMap1() {
String[] arr1 = {"a", "b", "c", "d"};
String[] arr2 = {"e", "f", "c", "d"};
String[] arr3 = {"h", "j", "c", "d"};
// Stream.of(arr1, arr2, arr3).flatMap(x -> Arrays.stream(x)).forEach(System.out::println);
Stream.of(arr1, arr2, arr3).flatMap(Arrays::stream).forEach(System.out::println);
}
/**
* flapMap:拆解流,将流中每一个元素拆解成一个流
*/
@Test
public void testFlatMap() {
List<SysPermission> permissions = new ArrayList<>();
SysPermission permission = new SysPermission();
permission.setId(1L);
permission.setName("管理员权限");
permission.setDescription("超级管理员权限");
permissions.add(permission);
List<SysRole> roles = new ArrayList<>();
SysRole sysRole = new SysRole();
sysRole.setId(1L);
sysRole.setName("ADMIN");
sysRole.setDescription("管理员角色");
sysRole.setPermissions(permissions);
roles.add(sysRole);
SysUser user = new SysUser();
user.setId(1L);
user.setName("stream");
user.setDescription("stream flatMap 拆解流");
user.setRoles(roles);
// 未判空处理
List<String> permission1 = roles.stream()
.flatMap(sysRole1 -> sysRole1.getPermissions().stream())
.map(SysPermission::getName)
.collect(Collectors.toList());
System.out.println(permission1);
user.setRoles(null);
// 空指针异常
/*List<String> permission2 = roles.stream()
.flatMap(sysRole1 -> sysRole1.getPermissions().stream())
.map(SysPermission::getName)
.collect(Collectors.toList());
System.out.println(permission2);*/
List<String> permission3 = (CollectionUtils.isEmpty(user.getRoles())
? new ArrayList<SysRole>() : user.getRoles()).stream()
.flatMap(role -> (CollectionUtils.isEmpty(role.getPermissions())
? new ArrayList<SysPermission>() : role.getPermissions()).stream())
.map(SysPermission::getName)
.collect(Collectors.toList());
System.out.println(permission3);
List<String> permission4 = Optional.ofNullable(user.getRoles())
.orElse(new ArrayList<>()).stream()
.flatMap(role -> Optional.ofNullable(role.getPermissions())
.orElse(new ArrayList<>()).stream())
.map(SysPermission::getName)
.collect(Collectors.toList());
System.out.println(permission4);
}
/**
* Comparator.comparing是一个键提取的功能 以下两个语句表示相同意义
*/
@Test
public void testSorted1_() {
// 按照字符长度排序
Arrays.stream(arr1).sorted((x, y) -> {
if (x.length() > y.length()) {
return 1;
} else if (x.length() < y.length()) {
return -1;
} else {
return 0;
}
}).forEach(System.out::println);
Arrays.stream(arr1).sorted(Comparator.comparing(String::length)).forEach(System.out::println);
}
/**
* 倒序 reversed(),java8泛型推导的问题,所以如果comparing里面是非方法引用的lambda表达式就没办法直接使用reversed()
* Comparator.reverseOrder():也是用于翻转顺序,用于比较对象(Stream里面的类型必须是可比较的) Comparator.
* naturalOrder():返回一个自然排序比较器,用于比较对象(Stream里面的类型必须是可比较的)
*/
@Test
public void testSorted2_() {
Arrays.stream(arr1).sorted(Comparator.comparing(String::length).reversed())
.forEach(System.out::println);
Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println);
Arrays.stream(arr1).sorted(Comparator.naturalOrder()).forEach(System.out::println);
}
/**
* thenComparing 先按照首字母排序 之后按照String的长度排序
*/
@Test
public void testSorted3_() {
Arrays.stream(arr1).sorted(Comparator.comparing(this::com1).
thenComparing(String::length)).forEach(System.out::println);
}
private char com1(String x) {
return x.charAt(0);
}
/*--------------提取流和合并流---------------------*/
String[] arr01 = new String[]{"a", "b", "c", "d"};
String[] arr02 = new String[]{"d", "e", "f", "g"};
String[] arr03 = new String[]{"i", "j", "k", "l"};
/**
* limit,限制从流中获得前n个数据
*/
@Test
public void testLimit() {
Stream.iterate(1, x -> x + 2).limit(10).forEach(System.out::println);
}
/**
* skip,跳过前n个数据
*/
@Test
public void testSkip() {
//Stream.of(arr1).skip(2).limit(2).forEach(System.out::println);
Stream.iterate(1, x -> x + 2).skip(1).limit(5).forEach(System.out::println);
}
/**
* 可以把两个stream合并成一个stream(合并的stream类型必须相同) 只能两两合并
*/
@Test
public void testConcat() {
Stream<String> stream1 = Stream.of(arr01);
Stream<String> stream2 = Stream.of(arr02);
Stream.concat(stream1, stream2).distinct().forEach(System.out::println);
}
private String[] arr05 = new String[]{"b", "ab", "abc", "abcd", "abcde"};
/**
* max、min 最大最小值
*/
@Test
public void testMaxAndMin() {
Stream.of(arr05).max(Comparator.comparing(String::length)).ifPresent(System.out::println);
Stream.of(arr05).min(Comparator.comparing(String::length)).ifPresent(System.out::println);
}
/**
* count 计算数量
*/
@Test
public void testCount() {
long count = Stream.of(arr05).count();
System.out.println(count);
}
/**
* findFirst 查找第一个
*/
@Test
public void testFindFirst() {
String str = Stream.of(arr05).parallel().filter(x -> x.length() > 3).findFirst()
.orElse("nothing");
System.out.println(str);
}
/**
* findAny 找到所有匹配的元素 对并行流十分有效 只要在任何片段发现了第一个匹配元素就会结束整个运算
*/
@Test
public void testFindAny() {
Optional<String> optional = Stream.of(arr05).parallel().filter(x -> x.length() > 3).findAny();
optional.ifPresent(System.out::println);
}
/**
* anyMatch 是否含有匹配元素
*/
@Test
public void testAnyMatch() {
Boolean aBoolean = Stream.of(arr05).anyMatch(x -> x.startsWith("a"));
System.out.println(aBoolean);
boolean a = Stream.of(arr05).allMatch(s -> s.startsWith("a"));
System.out.println(a);
}
/*--------- Optional类型通常聚合操作会返回一个Optional类型,Optional表示一个安全的指定结果类型,
所谓的安全指的是避免直接调用返回类型的null值而造成空指针异常,调用optional.ifPresent()可以判断返回值是否为空,
或者直接调用ifPresent(Consumer consumer)在结果部位空时进行消费操作;调用optional.get()获取返回值。
通常的使用方式如下:----*/
@Test
public void testStream1() {
Optional<Integer> optional = Stream.of(1, 2, 3)
.filter(x -> x > 1)
.reduce((x, y) -> x + y);
optional.ifPresent(System.out::println);
}
@Test
public void testOptional() {
List<String> list = new ArrayList<String>() {
{
add("user1");
add("user2");
}
};
Optional<String> opt = Optional.of("andy with u");
opt.ifPresent(list::add);
list.forEach(System.out::println);
}
/**
* 使用Optional可以在没有值时指定一个返回值,例如
*/
@Test(expected = RuntimeException.class)
public void testOptional2() {
Integer[] arr = new Integer[]{4, 5, 6, 7, 8, 9};
Integer result = Stream.of(arr).filter(x -> x > 9)
.max(Comparator.naturalOrder())
.orElse(-1);
System.out.println(result);
Integer result1 = Stream.of(arr).filter(x -> x > 9)
.max(Comparator.naturalOrder())
.orElse(-1);
System.out.println(result1);
Integer result2 = Stream.of(arr).filter(x -> x > 9)
.max(Comparator.naturalOrder())
.orElseThrow(RuntimeException::new);
System.out.println(result2);
}
/**
* Optional的创建 采用Optional.empty()创建一个空的Optional,使用Optional.of()创建指定值的Optional。
* 同样也可以调用Optional对象的map方法进行Optional的转换,调用flatMap方法进行Optional的迭代
*/
@Test
public void testStream02() {
Optional<User> studentOptional = Optional.of(new User("user1", 21));
Optional<String> optionalStr = studentOptional.map(User::getName);
System.out.println(optionalStr.get());
}
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
@Test
public void testInverse() {
Optional<Double> inverse = StreamTest.inverse(100.00);
System.out.println(inverse.get());
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
@Test
public void testSquareRoot() {
Optional<Double> aDouble = StreamTest.squareRoot(100.00);
System.out.println(aDouble.get());
}
/**
* Optional的迭代
*/
@Test
public void testStream2() {
double x = 4d;
Optional<Double> result1 = inverse(x).flatMap(StreamTest::squareRoot);
result1.ifPresent(System.out::println);
Optional<Double> result2 = Optional.of(4.0).flatMap(StreamTest::inverse)
.flatMap(StreamTest::squareRoot);
result2.ifPresent(System.out::println);
}
/* ----------------收集结果 ------------------------*/
User[] users;
@Before
public void init01() {
users = new User[20];
for (int i = 0; i < 10; i++) {
User user = new User((long) i, "user", 60 - i);
users[i] = user;
}
for (int i = 10; i < 20; i++) {
User user = new User((long) i, "user" + i, 100 - i);
users[i] = user;
}
}
@Test
public void testCollect1() {
// 生成List
List<User> list = Arrays.stream(users).collect(Collectors.toList());
list.forEach(System.out::println);
// 生成Set
Set<User> set = Arrays.stream(users).collect(Collectors.toSet());
set.forEach(System.out::println);
// 如果包含相同的key,则需要提供第三个参数,否则报错
Map<String, Integer> map = Arrays.stream(users)
.collect(Collectors.toMap(User::getName, User::getScore, (s, a) -> s + a));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* 生成数组
*/
@Test
public void testCollect2() {
User[] s = Arrays.stream(users).toArray(User[]::new);
for (User value : s) {
System.out.println(value);
}
}
/**
* 指定生成的类型
*/
@Test
public void testCollect3() {
HashSet<User> s = Arrays.stream(users).collect(Collectors.toCollection(HashSet::new));
s.forEach(System.out::println);
}
/**
* 统计
*/
@Test
public void testCollect4() {
IntSummaryStatistics summaryStatistics = Arrays.stream(users)
.collect(Collectors.summarizingInt(User::getScore));
System.out.println("getAverage->" + summaryStatistics.getAverage());
System.out.println("getMax->" + summaryStatistics.getMax());
System.out.println("getMin->" + summaryStatistics.getMin());
System.out.println("getCount->" + summaryStatistics.getCount());
System.out.println("getSum->" + summaryStatistics.getSum());
}
/* -----------------分组和分片 ---------------*/
/**
* 分组和分片的意义是,将collect的结果集展示位Map的形式,通常的用法如下:
*/
@Test
public void testGroupByName1() {
Map<String, List<User>> map = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* downstream指定类型
*/
@Test
public void testGroupByName2() {
Map<String, Set<User>> map = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName, Collectors.toSet()));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* 根据名字分组并映射value值
*/
@Test
public void testGroupByNameAndMapping() {
Map<String, List<Integer>> map = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName,
Collectors.mapping(User::getScore, Collectors.toList())));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* 根据多个字段分组
*/
@Test
public void groupByMultipleFields() {
Map<String, Map<Integer, User>> map = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName,
Collectors.toMap(User::getScore, Function.identity(), (old, replace) -> replace)));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* 如果只有两类,使用partitioningBy会比groupingBy更有效率
*/
@Test
public void testPartitioningBy() {
Map<Boolean, List<User>> map = Arrays.stream(users)
.collect(Collectors.partitioningBy(x -> x.getScore() > 50));
map.forEach((x, y) -> System.out.println(x + "->" + y));
}
/**
* downstream 聚合操作
*/
@Test
public void testGroupBy3() {
// counting
Map<String, Long> map1 = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName, Collectors.counting()));
map1.forEach((x, y) -> System.out.println(x + "->" + y));
}
@Test
public void testSummingInt() {
// summingInt
Map<String, Integer> map2 = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName, Collectors.summingInt(User::getScore)));
map2.forEach((x, y) -> System.out.println(x + "->" + y));
}
@Test
public void testMaxBy() {
// maxBy
Map<String, Optional<User>> map3 = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName,
Collectors.maxBy(Comparator.comparing(User::getScore))));
map3.forEach((x, y) -> System.out.println(x + "->" + y));
}
@Test
public void testMapping() {
// mapping
Map<String, Set<Integer>> map4 = Arrays.stream(users)
.collect(Collectors.groupingBy(User::getName,
Collectors.mapping(User::getScore, Collectors.toSet())));
map4.forEach((x, y) -> System.out.println(x + "->" + y));
}
/*-----------------------------原始类型流--------------------------------*/
/**
* 在数据量比较大的情况下,将基本数据类型(int,double…)包装成相应对象流的做法是低效的,
* 因此,我们也可以直接将数据初始化为原始类型流,在原始类型流上的操作与对象流类似,我们只需要记住两点:
* 1、原始类型流的初始化
* 2、原始类型流与流对象的转换
* DoubleStream doubleStream;
* IntStream intStream;
*/
/**
* 原始类型流的初始化
*/
DoubleStream doubleStream;
IntStream intStream;
@Before
public void testStream002() {
doubleStream = DoubleStream.of(0.1, 0.2, 0.3, 0.8);
intStream = IntStream.of(1, 3, 5, 7, 9);
IntStream stream1 = IntStream.rangeClosed(0, 100);
IntStream stream2 = IntStream.range(0, 100);
}
/**
* 流与原始类型流的转换
*/
@Test
public void testStream03() {
Stream<Double> stream = doubleStream.boxed();
doubleStream = stream.mapToDouble(Double::new);
}
/*--------------- 并行流 --------------------------*/
/**
* 我们调用peek方法来瞧瞧并行流和串行流的执行顺序,peek方法顾名思义,就是偷窥流内的数据, peek方法声明为Streampeek(Consumer
* action);加入打印程序可以观察到通过流内数据,见如下代码:
*/
public void peek1(int x) {
System.out.println(Thread.currentThread().getName() + ":->peek1->" + x);
}
public void peek2(int x) {
System.out.println(Thread.currentThread().getName() + ":->peek2->" + x);
}
public void peek3(int x) {
System.out.println(Thread.currentThread().getName() + ":->final result->" + x);
}
/**
* peek,监控方法 串行流和并行流的执行顺序
*/
@Test
public void testPeek() {
Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10);
stream.peek(this::peek1).filter(x -> x > 5)
.peek(this::peek2).filter(x -> x < 8)
.peek(this::peek3)
.forEach(System.out::println);
}
@Test
public void testPeekPal() {
Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10).parallel();
stream.peek(this::peek1).filter(x -> x > 5)
.peek(this::peek2).filter(x -> x < 8)
.peek(this::peek3)
.forEach(System.out::println);
}
@Test
public void testToMap() {
List<User> list = new ArrayList<>();
list.add(new User(1L, "haha", 60));
list.add(new User(2L, "rere", 70));
list.add(new User(3L, "fefe", 80));
Map<Long, User> map = list.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
System.out.println(map);
System.out.println(map.get(1L).getName());
Map<Long, String> collect = list.stream().collect(Collectors.toMap(User::getId, User::getName));
System.out.println(collect);
// 解决key冲突
list.add(new User(1L, "feifei", 90));
Map<Long, User> collect1 = list.stream()
.collect(Collectors.toMap(User::getId, Function.identity(), (old, replace) -> replace));
System.out.println(collect1);
}
@Test
public void testDistinct01() {
List<String> list = Lists.newArrayList("aa", "bb", "cc", "aa");
list.stream().distinct().forEach(System.out::println);
}
/**
* 根据名字和分数分组
*/
@Test
public void testUserGroupBy() {
List<User> list = new ArrayList<>();
User user1 = new User(1L, "aa", 86);
list.add(user1);
User user2 = new User(2L, "bb", 90);
list.add(user2);
User user3 = new User(3L, "cc", 95);
list.add(user3);
Map<User, List<User>> collect = list.stream().collect(Collectors.groupingBy(
record -> new User(record.getName(), record.getScore())));
System.out.println(collect);
}
}
Java8 新特性之Optional 的使用
于 2019-07-22 11:10:43 首次发布