package com.mayao.blog;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* function :用户示例
* @author :mayao
* @date :2018/4/14
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int index;
private String userName;
private int age;
private String sex;
public User(String userName, int age, String sex) {
this.userName = userName;
this.age = age;
this.sex = sex;
}
public User(int index, String userName, int age) {
this.index = index;
this.userName = userName;
this.age = age;
}
}
package com.mayao.stream;
import com.mayao.blog.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.lang.System.*;
/**
* function :Lambda表达式,Stream流的demo
* @author :mayao
* @date :2018/4/15
*/
@Slf4j
public class StreamInActionTest {
private List<User> userList;
private static String WOMAN = "女";
private static String MAN = "男";
@Before
public void initData(){
User user0 = new User("用户1",30,MAN);
User user1 = new User("用户2",17,WOMAN);
User user2 = new User("用户3",100,MAN);
User user3 = new User("用户4",39,WOMAN);
User user4 = new User("用户5",27,MAN);
User user5 = new User("用户6",15,MAN);
User user6 = new User("用户10",36,WOMAN);
User user7 = new User("用户11",24,WOMAN);
User user8 = new User("用户20",40,MAN);
User user9 = new User("用户21",100,WOMAN);
userList = Arrays.asList(user0,user1,user2,user3,user4,user5,user6,user7,user8,user9);
out.println(userList);
}
public static void println(Object object){
out.println(object);
}
/**
* 一对一的映射
*/
@Test
public void mapTest(){
List<String> stringList = Arrays.asList("a","s","v","e","q");
stringList = stringList.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
userList = userList.stream()
.map(user -> {
user.setAge(user.getAge()+5);
return user;
}).collect(Collectors.toList());
List<Integer> nums = Arrays.asList(1,2,3,4);
nums = nums.stream()
.map(num -> num * num)
.collect(Collectors.toList());
System.out.println("map 平方数:"+nums);
/**
* 不难发现,map都是一对一的映射操作,多行逻辑用大括号:{}
*/
}
/**
* 一对多的映射
*/
@Test
public void flatMapTest(){
Stream<List<Integer>> inputStream = Stream.of(
Arrays.asList(1,2,3),
Arrays.asList(3,4),
Arrays.asList(5,6)
);
Stream<Integer> outputStream = inputStream
.flatMap(subList -> subList.stream());
List<Integer> list = outputStream.collect(Collectors.toList());
println(list);
/**
* flatMap 把 input Stream 中的层级结构扁平化,将底层元素抽出来放到一起
* 最终: output Stream 中里面已经没有List了,都是直接的数字
*/
}
/**
* 过滤操作
*/
@Test
public void filterTest(){
userList = userList.stream()
.filter(user -> user.getSex().equals(WOMAN))
.collect(Collectors.toList());
userList = userList.stream()
.filter(user -> user.getSex().equals(WOMAN))
.map(user -> {
user.setAge(18);
return user;
})
.collect(Collectors.toList());
/**
* 发现没有,流--》数据规则--》数据处理--》结果
* 其实规则也是数据处理
* 本质是:流数据--》数据处理--》结果
*/
}
/**
* 循环
*/
@Test
public void foreachTest(){
userList.stream()
.filter(user -> user.getSex().equals(MAN))
.forEach(user -> System.out.println(user.getAge()));
/**
* foreach 是 terminal(终端)操作,一个流不能重复多次使用。不能在后面再接一个 foreach,比如:
* 但是在 intermediate(中间)操作,peek操作可以替代
*/
userList.stream()
.filter(user -> user.getAge()>18)
.peek(user -> System.out.println(user.getAge()))
.filter(user -> user.getSex().equals(WOMAN))
.peek(user -> System.out.println(user.getSex()))
.collect(Collectors.toList());
}
/**
*findFirst
*/
@Test
public void findFirstTest(){
Optional<User> userOptional = userList.stream()
.findFirst();
User user = userOptional.get();
log.info("第一个用户:{}",user);
userOptional.isPresent();
System.out.println(Optional.ofNullable(user).isPresent());
Integer age = userList.stream()
.map(User::getAge)
.findFirst()
.get();
log.info("第一个年纪:{}",age);
}
/**
* Optional相关用法认识
* 下面有两个用例
* 在更复杂的 if( x != null) 的情况中,使用Optional代码的可读性更好,而且它提供了的是编译时检查,
* 能极大的见地NPE这种 RuntimeException 运行时异常对程序的影响,让程序员在更早的编译阶段处理
* 空值的问题;;
* Stream 中 findAny,max/min,reduce 等都返回的是Optional值;
* IntStream.average() 返回 OptionalDouble 等等;;
*/
@Test
public void optionalTest(){
String strA = "abcd",strB = null;
printTest(strA);
getStrLengthTest(strA);
Optional optional = Optional.empty();
Optional<User> userOptional = Optional.of(new User("这是一个新用户",28,MAN));
User user27 = userOptional.filter(c->c.getAge()<27).orElse(new User("没有用户",-1,MAN));
log.info(user27.toString());
}
private void printTest(String string){
Optional.ofNullable(string).ifPresent(System.out::print);
Optional.ofNullable(string).ifPresent(c ->{
c = c.toUpperCase();
log.info("optional多行语句操作:{}",c);
});
if( null != string){
log.info("pre java8 print:{}",string);
}
boolean isNull = Optional.ofNullable(string).isPresent();
log.info("是否存在:{}",isNull);
}
private void getStrLengthTest(String string){
int length = Optional.ofNullable(string).map(String::length).orElse(-1);
log.info("java8 :{},长度:{}",string,length);
int length2 = null != string ? string.length() : -1;
log.info("pre java8 :{},长度:{}",string,length2);
}
/**
* 排序
*/
@Test
public void sorted(){
Set<Integer> set = Stream.of(2,5,1,7,9,5).sorted().collect(Collectors.toSet());
log.info("Interger的排序:{}",set);
userList = userList.stream()
.sorted(Comparator.comparing(User::getAge))
.collect(Collectors.toList());
log.info("根据年龄排序结果:{}",userList);
userList = userList.stream()
.sorted(Comparator.comparing(User::getUserName))
.collect(Collectors.toList());
log.info("根据用户姓名排序结果:{}",userList);
}
/**
* 聚合操作:
* sum 求和
* min 最小
* max 最大
* distinct 唯一
*
*/
@Test
public void sumMinMaxDistinct(){
int sum = userList.stream().
mapToInt(User::getAge)
.sum();
log.info("年龄总和:{}",sum);
OptionalInt optionalInt = userList.stream()
.mapToInt(User::getAge)
.min();
int min = optionalInt
.getAsInt();
log.info("年龄最小:{}",min);
int max = userList.stream().mapToInt(User::getAge)
.max()
.getAsInt();
log.info("年龄最大:{}",max);
List<String> sex = userList.stream()
.map(User::getSex)
.distinct()
.collect(Collectors.toList());
log.info("性别集合为:{}",sex);
}
/**
* 这个方法主要是把Stream元素组合起来。
* 它提供一个起始值-》规则操作-》结果组合起来
*
*/
@Test
public void reduce(){
int sum = IntStream.of(1,2,3,4,5).reduce((a,b) -> a+b).getAsInt();
log.info("reduce sum 无初始值:{}",sum);
int sum2 = IntStream.of(1,2,3,4,5).reduce(100,(a,b) -> a+b);
log.info("reduce sum2 有初始值:{}",sum2);
String reduceStrConcat = Stream.of("A","a","b","C","e","E")
.filter(c -> c.compareTo("Z")>0)
.reduce("",String::concat);
log.info("reduce filter string concat :{}",reduceStrConcat);
/**
* 所以,min,max,average 都是特殊的reduce操作
*/
}
/**
* limit:返回stream前面的几个元素
* skip:扔掉前面几个元素
*/
@Test
public void limitSkip(){
userList = userList.stream()
.limit(5L)
.collect(Collectors.toList());
println("limit 前面的五个元素:"+userList);
userList = userList.stream()
.skip(2L)
.collect(Collectors.toList());
println("skip 五个元素再去掉前面两个:"+userList);
}
/**
* allMatch:所有符合条件的值
* anyMatch:Boolean值,一个符合传入的值就返回true
* noneMatch:没有一个符合的值就返回true
*
*/
@Test
public void match(){
boolean allMatch = userList.stream().allMatch(c->c.getAge()<101);
println("所有用户都小于101岁:"+allMatch);
boolean anyMatch =userList.stream().anyMatch(c->c.getAge()<20);
println("至少有一个用户小于20岁:"+anyMatch);
boolean noneMatch = userList.stream().noneMatch(c->c.getSex().equals(MAN));
println("用户都是男的:"+noneMatch);
/**
* 延伸:
* anyMatch 让我想起了 List(T t).contains(T t);
* //这是源码
* public boolean contains(Object o) {
return indexOf(o) >= 0;
}
//indexOf
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
anyMatch..源码暂时看的有点晕,有兴趣的可以去看看
*
*/
}
/**
* used in lambda shoudle be final or efftively final
* 语法糖解决
*
*/
@Test
public void shoudbleFinalTest(){
List<String> strings = new ArrayList<>();
strings.add(MAN);
if( 1==strings.size() ){
List<String> strings2 = Arrays.asList(WOMAN);
strings.addAll(strings2);
}
userList.forEach(c->{
println(strings);
});
}
}