package com.lambda.demo;
import com.lambda.demo.exception.CanNotGetUserExceptionSupplier;
import com.lambda.demo.model.User;
import com.lambda.demo.model.UserSupplier;
import org.junit.Test;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Stream 简单操作
* https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
*
* @author Jake.Woo
* <p>
* Stream 操作简单介绍:
* 每一个Stream 中的数据只能被使用一次.所以Stream API 大体可以分为两种操作类型:
* 1. intermediate (中间操作) 不会立即产生结果的操作.
* map (mapToInt, flatMap 等)、 filter、 distinct、
* sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
* 2. terminal (最终操作) 每个Stream 只能有一个Terminal 操作
* forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、
* max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
* 当切仅当Terminal 性质的API 被调用的时候,Stream 中的数据才会被真正的使用
* 类似于,StringBuffer 的append 和toString 方法 toString 时,才会生成想要的String 对象
* 还有一种针对无限大的Stream 做过滤的操作,在无限大的Stream 中获取一个新的有限的Stream
* anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
*/
public class StreamDemo {
/**
* reduction :
* 通过{@link java.util.stream.Collectors} 辅助
*/
@Test
public void reductionDemo() {
//归档--按照user age 进行归档 返回结果key 为age value 为age 下的集合
Map<Integer, List<User>> collect =
Stream.generate(new UserSupplier()).limit(100)
.collect(Collectors.groupingBy(User::getAge));
collect.forEach((age, user) -> System.out.println("age:" + age + ", user:" + user));
//分片. 年龄大于等于十八岁的,年龄小于十八岁的
Map<Boolean, List<User>> collect1 =
Stream.generate(new UserSupplier()).limit(100)
.collect(Collectors.partitioningBy(user -> user.getAge() > 18));
collect1.forEach((age, user) ->
System.out.println("age > 18:" + age
+ ", user:" + user.size()));
}
/**
* iterate 接受一个初始值 和一个运算规则 生成Stream
*/
@Test
public void iterateDemo() {
//等差数列
Stream.iterate(0, n -> n + 3)
.limit(10)
.forEach(System.out::println);
}
/**
* 生成流,需要limit 限制数量
*/
@Test
public void generateDemo() {
Random random = new Random();
List<Integer> collect = Stream
.generate(random::nextInt)
.limit(13).sorted()
.peek(num -> System.out.println(num + ", "))
.skip(5).collect(Collectors.toList());
collect.forEach(System.out::println);
Stream.generate(new UserSupplier())
.limit(5).peek(System.out::println)
.collect(Collectors.toList());
}
/**
* allMatch: Stream 中所有元素都满足 返回true
* anyMatch: 有一个满足 返回true
* noneMatch: 没有一个元素满足 返回true
*/
@Test
public void matchDemo() {
System.out.println(
"all user age > 18? "
+ userStream().allMatch(user -> user.getAge() > 18));
System.out.println(
"there is a user age = 18? "
+ userStream().anyMatch(user -> user.getAge() == 18));
System.out.println(
"not a user age < 18? "
+ userStream().noneMatch(user -> user.getAge() < 18));
}
/**
* 过滤.唯一
*/
@Test
public void distinctDemo() {
Stream.of("abc", "def", "acb", "abc", "def")
.distinct().
map(String::toLowerCase)
// .sorted()
.collect(Collectors.toList())
.forEach(System.out::println);
}
@Test
public void maxDemo() {
System.out.println(
Stream.of(3, 2, 1, 6, 5, 7, 9, 4)
.max(Integer::compareTo)
.get());
}
@Test
public void minDemo() {
System.out.println(
Stream.of(3, 2, 1, 6, 5, 7, 9, 4)
.min(Integer::compareTo)
.get());
}
/**
* 对流中的数据进行排序
*/
@Test
public void sortedDemo() {
Stream.of(3, 1, 2, 6, 5, 7, 9, 4)
.sorted().forEach(System.out::println);
System.out.println("------");
userStream().sorted((user1, user2) -> user2.getAge()
.compareTo(user1.getAge())).forEach(System.out::println);
}
/**
* limit: 返回Stream 前面几个元素
* skip: 扔掉前面几个元素
*/
@Test
public void limitAndSkipDemo() {
Stream.of(3, 1, 2, 6, 5, 7, 9, 4).limit(5).forEach(System.out::println);
System.out.println("-----");
Stream.of(3, 1, 2, 6, 5, 7, 9, 4).skip(2).forEach(System.out::println);
}
/**
* reduce 将stream 中的数据做合并,最终返回一个结果
*/
@Test
public void reduceDemo() {
//一个参数 参数为数据处理方式 返回结果是一个optional 实例
Stream<Integer> integerStream = integerStream();
Integer integer = integerStream.reduce((a, b) -> a + b).get();
System.out.println(integer);
//两个参数: 第一个参数为初始元素,如果stream 中没有元素,则返回初始元素
//如果有元素,则初始元素将参与运算
Stream<Integer> integerStream2 = Stream.of(0);
Integer reduce = integerStream2.reduce(-1, (a, b) -> a + b);
System.out.println(reduce);
//三个参数: 基本与两个参数类似
//第三个参数针对的是并行操作涉及到的结果集的处理
//非并行模式,第三个参数不会被调用到
ArrayList<User> userList =
userStream().reduce(
new ArrayList<User>(), (list, user) -> {
list.add(user);
return list;
}, new BinaryOperator<ArrayList<User>>() {
@Override
public ArrayList<User> apply(ArrayList<User> list1,
ArrayList<User> list2) {
System.out.println("我调用了这个方法");
return list1;
}
});
userList.forEach(System.out::println);
//并行模式下,第三个参数是对并行模式下数据归并的处理逻辑
Integer reduce1 =
Stream.of(1, 2, 3, 4, 5).parallel()
.reduce(4, (a, b) -> a + b, (c, d) -> c + d);
System.out.println(reduce1);
//最后结果为35, 因为并行处理,且线程间的独立性.使得每个元素都被加了identity
//因此最后的结果为所有元素都加了identity 之后的和
}
/**
* 获取Stream 第一个元素,或者空
*/
@Test
public void findFirstDemo() {
Stream<User> userStream = userStream();
Optional<User> first = userStream.findFirst();
System.out.println(first.orElseThrow(new CanNotGetUserExceptionSupplier()));
System.out.println(userStream.findAny().get());
}
/**
* 流转换为对象
*/
@Test
public void transitionDemo() {
Stack<Integer> intStack =
integerStream()
.collect(Collectors.toCollection(Stack::new));
intStack.forEach(System.out::println);
Set<String> stringSet =
stringStream().collect(Collectors.toSet());
stringSet.forEach(System.out::println);
User[] userArr = userStream().toArray(User[]::new);
Arrays.stream(userArr).forEach(System.out::println);
}
/**
* Map操作: 将Stream 中的元素按照传入的规则映射成新的元素
* emmmm... 不是我们理解的那个Map 集合 只是表示一种映射操作
*/
@Test
public void mapDemo() {
Stream<Integer> stream = integerStream();
stream.map(num -> num * 100).forEach(System.out::println);
}
/**
* flatMap :将Stream 中的多个对象,合并成一个对象
*/
@Test
public void flatMapDemo() {
Stream<List<Integer>> listStream =
Stream.of(Arrays.asList(1, 3, 5), Arrays.asList(2, 4, 6));
listStream.flatMap(Collection::stream).forEach(System.out::print);
//listStream.flatMap(list->list.stream()).forEach(System.out::print);
}
/**
* Filter 将数据按照条件进行过滤
*/
@Test
public void filterDemo() {
userStream().filter(user -> user.getAge() == 21)
.forEach(System.out::println);
}
/**
* peek 对每个元素进行操作,但是不是立即执行.遇到Terminal 操作时,才会逐一对元素执行所有的peek 操作
*/
@Test
public void peekDemo() {
userStream().peek(System.out::println).filter(user -> user.getName().length() > 1)
.peek(user -> user.setAge(user.getAge() + 10)).forEach(System.out::println);
}
/**
* 创建一个user Stream 对象
*
* @return
*/
public Stream<User> userStream() {
List<User> list = new ArrayList<>();
list.add(new User("张三", 21));
list.add(new User("李四", 33));
list.add(new User("王五", 18));
return list.stream();
//并行流
// return list.stream().parallel();
// return list.parallelStream();
}
/**
* 创建一个String Stream 对象
*
* @return
*/
public Stream<String> stringStream() {
String[] arr = new String[]{"张三", "李四",
"王五", "赵六", "周扒皮", "靓妹", "帅哥"};
return Arrays.stream(arr);
// return Stream.of(arr);
}
/**
* 创建一个 integer Stream 对象
*
* @return
*/
public Stream<Integer> integerStream() {
return Stream.of(1, 11, 22, 3, 44, 5, 32, 51, 66);
}
}
package com.lambda.demo;
import com.lambda.demo.exception.CanNotGetUserExceptionSupplier;
import com.lambda.demo.model.User;
import com.lambda.demo.model.UserSupplier;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @author Jake.Woo
* optional 主要解决NPE 问题
* 大概包含如下API
* 创建一个Optional of ofNullable
* 判断是否有实例数据 isPresent
* 获取实例 get orElse orElseGet orElseThrow
* 对实例进行操作 map flatMap
* 过滤 filter
*/
public class OptionalDemo {
/**
* flatMap
* 操作和{@link #mapDemo()}类似 但是返回结果是Optional 类型
*/
@Test
public void flatMap() {
Optional<String> stringOptional = Optional.of("aBcDeFg");
// Optional<String> stringOptional = Optional.empty();
System.out.println(stringOptional
.flatMap(val -> Optional.of(val.substring(0, 3)))
.orElse("no value"));
System.out.println(stringOptional
.map(val -> val.substring(0, 3))
.orElse("no value"));
}
/**
* map
* 对optional 内的元素进行操作,
* 如果元素为空,不做处理并返回null
*/
@Test
public void mapDemo() {
Optional<String> stringOptional = Optional.of("aBcDeFg");
// Optional<String> stringOptional = Optional.empty();
System.out.println(
stringOptional.map(String::toUpperCase)
.orElse("no value"));
}
/**
* filter
*/
@Test
public void filterDemo() {
Optional<String> stringOptional = Optional.of("abcde");
System.out.println("过滤之后,是否还有数据: "
+ stringOptional.filter(val -> val.length() > 3)
.isPresent());
}
/**
* orElseThrow
* 获取一个实例.如果没有, 通过实现supplier 接口的自定义异常,获取一个异常抛出
*/
@Test
public void orElseThrowDemo() {
System.out.println(Optional.empty()
.orElseThrow(
new CanNotGetUserExceptionSupplier()));
}
/**
* orElseGet
* 获取对象.如果没有,通过supplier 获取一个实例
*/
@Test
public void orElseGetDemo() {
Optional<User> objectOptional = Optional.empty();
System.out.println(objectOptional.orElseGet(new UserSupplier()));
}
/**
* orElse 如果不存在,返回传入的对象
*/
@Test
public void orElseDemo() {
Optional<Object> objectOptional = Optional.of("我是初始值");
System.out.println(objectOptional.orElse("没有值得时候.返回值就是我"));
System.out.println("---------");
objectOptional = Optional.empty();
System.out.println(objectOptional.orElse("没有值得时候.返回值就是我"));
}
/**
* get 如果值为null 抛出异常
* NoSuchElementException: No value present
* 否则,返回该值
*/
@Test
public void getDemo() {
Optional<Object> objectOptional = Optional.of(new Object());
System.out.println(objectOptional.get());
Optional<Object> empty = Optional.empty();
System.out.println(empty);
System.out.println(empty.get());
}
/**
* 返回一个值为null的 Optional
*/
@Test
public void emptyDemo() {
Optional<Object> empty = Optional.empty();
empty.ifPresent(System.out::println);
System.out.println("Optional is Present: " + empty.isPresent());
}
/**
* isPresent 是否存在(是否不为空)
*/
@Test
public void isPresentDemo() {
Optional<Integer> optAsNull = Optional.ofNullable(null);
System.out.println("optAsNull: " + optAsNull.isPresent());
Optional<Integer> opt = Optional.of(1);
System.out.println("optNotNull: " + opt.isPresent());
}
/**
* if Present 如果存在,做点什么
*/
@Test
public void ifPresentDemo() {
//ifPresent 如果存在,就做点什么.
List<Integer> list = new ArrayList<>();
Optional.of(1).ifPresent(list::add);
Optional.of(10).ifPresent(list::add);
//如果不存在,不进行操作
Optional.ofNullable(null).ifPresent(val->{
System.out.println(val);
list.add((Integer) val);
});
System.out.println("-----");
list.forEach(System.out::println);
}
/**
* 三种创建方式
*/
@Test
public void createDemo(){
//of : 必须有值且不为null
Optional.of(10);
//ofNullable : 必须有值,可以为null
Optional.ofNullable(null);
//empty : 创建一个值为null 的实例
Optional.empty();
}
}