java8新特性
Stream 流处理
去重
- 去重复值
list.stream().distinct().collect(Collections.toList());
- 自定义去重(不保留原来的排序)
//根据name属性去重
List<User> lt = list.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList::new));
System.out.println("去重后的:" + lt);
//根据name与address属性去重
List<User> lt1 = list.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName() + ";" + o.getAddress()))), ArrayList::new));
System.out.println("去重后的:" + lt);
- 自定义去重(保留原来排序)
List<User> lt = list.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))),v -> v.stream().sorted().collect(Collectors.toList())));
过滤
- 过滤掉不满足条件的
userList = userList.stream().filter(user -> "广州".equals(user.getName())).collect(Collectors.toList());
- 获取第一条满足条件的数据
//.findFirst().orElse(null)
User user = userList.stream().filter(u -> "深圳".equals(u.getName())).findFirst().orElse(null);
- 正则表达式过滤
- 将null值过滤
.stream().map(FileDataInfo::getNumCode).filter(Objects::nonNull).collect(Collectors.toList());
提取 转换 分组
- List 转List
List<String> nameList= userList.stream().map(User::getName).collect(Collectors.toList());
- 分组: (List转Map<String,List)
Map<String,List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getName));
- 高级分组 List《Object》 转 Map<String,List《String》>
List<SampleFileLink> sampleFileLinkList = sampleFileLinkDao.findAllBySampleIdIn(sampleRidList);
//sampleRid->[FileInfoRid,FileInfoRid]
Map<String,List<String>> sampleRidAndFileInfoRidListMap = sampleFileLinkList.stream()
.collect(Collectors.groupingBy(SampleFileLink::getSampleId, Collectors.mapping(sampleFileLink -> sampleFileLink.getFileId(), Collectors.toList())));
- List《User》转Map<String,String>
限制数量
- 只取前 n 个
public static void main(String[] args) {
List<Integer> lists = Arrays.asList(1,2,3,4,5);
int n = lists.size() - 1;
lists = lists.stream().limit(n).collect(Collectors.toList());
System.out.println(lists.toString());//[1, 2, 3, 4]
}
-
跳过m条数据
.stream().skip(m) -
手动分页
public static void main(String[] args) {
List<Integer> lists = Arrays.asList(1,2,3,4,5);
int page = 2;
int rows = 3;
//skip(m):跳过前面m条数据
lists = lists.stream().skip((page - 1)*rows).limit(rows).collect(Collectors.toList());
System.out.println(lists.toString());//[4, 5]
}
判断
- 查询是否包含某条数据
Boolean isContain = userList.stream().anyMatch(user -> "广州".equals(user.getName()));
排序
- 升序和降序
//升序
userList = userList.stream().sorted(Comparator.comparingInt(User:: getAge)).collect(Collectors.toList());
//降序
.stream().sorted(Comparator.comparingInt(User:: getAge).reversed())
- 为null的值放最后或最前面
//放最后面
stream().sorted(Comparator.comparing(User::getAge,Comparator.nullsLast(Integer::compareTo)))
//最前面
stream().sorted(Comparator.comparing(User::getAge,Comparator.nullsFirst(Integer::compareTo)))
统计 和 计算
最大值,最小值,平均值,求和
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.*;
public class Test {
public static void main(String[] args) {
initEmp();
//求和
int sum = empList.stream().mapToInt(Employee -> Employee.getAge()).sum();
//最大值
int max = empList.stream().mapToInt(Employee -> Employee.getAge()).max().getAsInt();
//最小值
int min = empList.stream().mapToInt(Employee -> Employee.getAge()).min().getAsInt();
//平均值
double avg = empList.stream().mapToInt(Employee -> Employee.getAge()).average().getAsDouble();
System.out.println("最大值:" + max + "\n最小值:" + min + "\n总和:" + sum + "\n平均值:" + avg);
}
static List<Employee> empList = new ArrayList<Employee>();
private static void initEmp() {
empList.add(new Employee("张三", 30));
empList.add(new Employee("张三1", 96));
empList.add(new Employee("张三2", 23));
empList.add(new Employee("张三3", 69));
empList.add(new Employee("张三4", 85));
empList.add(new Employee("张三5", 62));
empList.add(new Employee("张三6", 12));
empList.add(new Employee("张三7", 99));
empList.add(new Employee("张三8", 11));
}
}
@Data
@AllArgsConstructor
class Employee {
private int id;
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
}
Optional null判断
用于判断null值的一些麻烦处理
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@ToString
class UserInfo {
private String username;
private String password;
private Integer age;
private String gender;
}
对象null判断
public static void main(String[] args) {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("yinwen");
Optional<UserInfo> userInfoOptional = Optional.of(userInfo);
if(userInfoOptional.isPresent()){
System.out.println(userInfoOptional.get().getUsername());//yinwen
}
}
当为null则提供默认值
//当optional里值为null,则返回一个new UserInfo()
UserInfo userInfo2 = userInfoEmptyOpt.orElse(new UserInfo());
当为null抛出异常
UserInfo userInfo4 = userInfoOpt.orElseThrow(NullPointerException::new);
Optional《Obj》 转 Optional《String》
Optional<UserInfo> userInfoOpt = Optional.of(new UserInfo("阿飞""));
Optional<String> username = userInfoOpt.map(UserInfo::getUsername);
Function 运算
函数式接口:用作算术封装
算术/逻辑 封装
public static void main(String[] args) {
Function<Integer,Integer> f1 = t -> (t + 3) * 2;
Function<Integer,Integer> f2 = t -> t * 10;
Function<Integer,Integer> f221 = f1.compose(f2).compose(f2);
Function<Integer,Function<Integer,Integer>> f3 = x -> (y -> (x + y));
Function<Integer,Function<Integer,Integer>> f13 = f3.compose(f1);
Function<Integer,Function<Integer,Integer>> f123 = f3.compose(f1).compose(f2);
//单函数使用
int a = f1.apply(5);//(5+3)*2 = 16
//函数嵌套 (先执行两次f2,再套入f1)
int b = f221.apply(4);// (( (4*10) * 10 ) + 3) * 2 = 806
//多参数使用
int c = f3.apply(1).apply(2);// 1 + 2 = 3
//多参数嵌套使用
int d = f13.apply(1).apply(2);//((1 + 3) * 2) + 2 = 10
int f = f123.apply(1).apply(2);//((1 + 3) * 2) + (2 * 10) = 28
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
System.out.println(f);
}
Predicate 判断
函数式接口: 用作判断
Predicate<String> p = o -> o.equals("test");
Predicate<String> g = o -> o.startsWith("t");
System.out.println(p.test("test"));//true
/**
* negate: 用于对原来的Predicate做取反处理;
* 如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;
*/
System.out.println(p.negate().test("test"));//false
/**
* and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
*/
System.out.println(p.and(g).test("test"));//true
/**
* or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
*/
System.out.println(p.or(g).test("ta"));//true
Consumer 操作
函数式接口:对元素执行某个操作 : 定义好函数式接口(方法)后可用lambda表达式进行自定义的多个操作。
andThen(Consumer com) //将Consumer连接
accept(数据) //使用Consumer操作数据
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
//传递的参数为一个字符串、两个Lambda表达式
method("Hello",
(str)->{
//对"Hello"自定义处理
System.out.println("com1: " + str.toUpperCase());//com1: HELLO
},
(str)->{
//对"Hello"自定义处理
System.out.println(str);//Hello
System.out.println("com2: " + str.length());//com2: 5
});
//输出: HELLO 5
}
/*
定义一个方法,方法的泛型指定为String,传递的参数为字符串类型的数据和两个Consumer接口,调用accept方法使用该数据
*/
public static void method(String str, Consumer<String> con1, Consumer<String> con2){
/*con1.accept(str);
con2.accept(str);*/
//使用endThen方法,将两个Consumer接口连接在一块
con1.andThen(con2).accept(str);//先执行con1使用数据,在执行con2使用数据,数据是相互隔离的
}
}