JAVA8新特性集
Stream流🎇
filter使用
//如果满足条件的对象存在
User user = userList.stream()
.filter(t -> 1 == t.getId())
.findAny()
.get();
//如果对象不存在,则会抛出异常:java.util.NoSuchElementException: No value present
User e = userList.stream()
.filter(t -> 3 == t.getId())
.findAny()
.get();
//如果对象不存在则返回特定对象
User n = userList.stream()
.filter(t -> 3 == t.getId())
.findAny()
.orElse(null);
//判断对象是否存在
boolean b = userList.stream()
.filter(t -> 3 == t.getId())
.findAny()
.isPresent();
// 示例三:通过与 mapToInt 计算和
List<User> lists = new ArrayList<User>();
lists.add(new User(6, "张三"));
lists.add(new User(2, "李四"));
lists.add(new User(3, "王五"));
lists.add(new User(1, "张三"));
// 计算这个list中出现 "张三" id的值
int sum = lists.stream()
.filter(u -> "张三".equals(u.getName()))
.mapToInt(u -> u.getId()).sum();
flatMap使用
// Stream流的flatMap使用
// flatMap 方法用于映射每个元素到对应的结果,一对多
String worlds = "The way of the future";
List<String> list7 = new ArrayList<>();
list7.add(worlds);
List<String> list8 = list7.stream()
.flatMap(str -> Stream.of(str.split(" ")))
.filter(world -> world.length() > 0)
.collect(Collectors.toList());
limit使用
//示例一:获取前n条数的数据
Random rd = new Random();
System.out.println("取到的前三条数据:");
rd.ints().limit(3).forEach(System.out::println);
// 示例二:结合skip使用得到需要的数据:skip表示的是扔掉前n个元素
List<User> list9 = new ArrayList<User>();
for (int i = 1; i < 4; i++) {
User user = new User(i, "pancm" + i);
list9.add(user);
}
System.out.println("截取之前的数据:");
// 取前3条数据,但是扔掉了前面的2条,可以理解为拿到的数据为 2<=i<3 (i 是数值下标)
List<String> list10 = list9.stream()
.map(User::getName)
.limit(3)
.skip(2)
.collect(Collectors.toList());
System.out.println("截取之后的数据:" + list10);
// 截取之前的数据:
// 姓名:pancm1
// 姓名:pancm2
// 姓名:pancm3
// 截取之后的数据:[pancm3]
sort使用
1、单字段排序
//按年龄排序(Integer类型)-正序
List<StudentInfo> studentsSortName = studentList.stream()
.sorted(Comparator.comparing(StudentInfo::getAge))
.collect(Collectors.toList());
//按年龄排序(Integer类型)-逆序
List<StudentInfo> studentsSortName = studentList.stream()
.sorted(Comparator.comparing(StudentInfo::getAge)
.reversed())
.collect(Collectors.toList());
2、多字段排序
List<StudentInfo> list = userList.stream()
.sorted(Comparator.comparing(UserDto::getUserRoleZt,Comparator.nullsLast(Integer::compareTo))
.thenComparing(UserDto::getUserStatus)
// reversed 降序
.reversed())
.collect(Collectors.toList());
3、对Null值进行排序
// 对象属性可能存在null值,不进行处理则会报NPE异常
// nullsLast:null值排在后面
// nullsFirst:null值排在前面
List<StudentInfo> list =userList.stream()
.sorted(Comparator.comparing(UserDto::getUserRoleZt,Comparator.nullsLast(Integer::compareTo))
.reversed())
.collect(Collectors.toList());
4、List<Map<String, Object>> 排序
List<Map<String, Object>> cats = new ArrayList<>();
Map<String,Object> cat1 = new HashMap<>();
cat1.put("name", "cat1");
cat1.put("age", 10);
cats.add(cat1);
Map<String,Object> cat2 = new HashMap<>();
cat2.put("name", "cat2");
cat2.put("age", 2);
cats.add(cat2);
List<Map<String, Object>> sortedCats = cats.stream().sorted((map1, map2) -> {
int age1 = (int) map1.getOrDefault("age", 0);
int age2 = (int) map2.getOrDefault("age", 0);
return age1 - age2;
}).collect(Collectors.toList());
sortedCats.forEach(System.out::println);
5、其他示例
// 示例一:随机取值排序
Random rd2 = new Random();
System.out.println("取到的前三条数据然后进行排序:");
rd2.ints().limit(3).sorted().forEach(System.out::println);
// 示例二:优化排序 tips:先获取在排序效率会更高!
//普通的排序取值
List<User> list11 = list9.stream()
.sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
.limit(3)
.collect(Collectors.toList());
//优化排序取值
List<User> list12 = list9.stream()
.limit(3)
.sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
.collect(Collectors.toList());
peek使用
peek对每个元素执行操作并返回一个新的Stream
// 示例:双重操作
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("转换之前: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("转换之后: " + e))
.collect(Collectors.toList());
// 转换之前: three
// 转换之后: THREE
// 转换之前: four
// 转换之后: FOUR
max/min/distinct使用
// 示例一:得到最大最小值
List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xiwqjing");
int maxLines = list13.stream()
.mapToInt(String::length)
.max()
.getAsInt();
int minLines = list13.stream()
.mapToInt(String::length)
.min()
.getAsInt();
System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
//最长字符的长度:8,最短字符的长度:4
//示例二:得到去重之后的数据
String lines = "good good study day day up";
List<String> list14 = new ArrayList<String>();
list14.add(lines);
List<String> words = list14.stream()
.flatMap(line -> Stream.of(line.split(" ")))
.filter(word -> word.length() > 0)
.map(String::toLowerCase)
.distinct()
.sorted()
.collect(Collectors.toList());
System.out.println("去重复之后:" + words);
//去重复之后:[day, good, study, up]
Match使用
allMatch:Stream 中全部元素符合则返回 true ;
anyMatch:Stream 中只要有一个元素符合则返回 true;
boolean all = lists.stream()
.allMatch(u -> u.getId() > 3);
System.out.println("是否都大于3:" + all);
boolean any = lists.stream()
.anyMatch(u -> u.getId() > 3);
System.out.println("是否有一个大于3:" + any);
boolean none = lists.stream()
.noneMatch(u -> u.getId() > 3);
System.out.println("是否没有一个大于3的:" + none);
// 是否都大于3:false
// 是否有一个大于3:true
// 是否没有一个大于3的:false
reduce使用
reduce 主要作用是把 Stream 元素组合起来进行操作
// 示例一:字符串连接
String concat = Stream.of("A", "B", "C", "D")
.reduce("", String::concat);
System.out.println("字符串拼接:" + concat);
// 示例二:得到最小值
double minValue = Stream.of(-4.0, 1.0, 3.0, -2.0)
.reduce(Double.MAX_VALUE, Double::min);
System.out.println("最小值:" + minValue);
//最小值:-4.0
// 示例三:求和
// 求和, 无起始值
int sumValue = Stream.of(1, 2, 3, 4)
.reduce(Integer::sum)
.get();
System.out.println("有无起始值求和:" + sumValue);
// 求和, 有起始值
sumValue = Stream.of(1, 2, 3, 4)
.reduce(1, Integer::sum);
System.out.println("有起始值求和:" + sumValue);
// 有无起始值求和:10
// 有起始值求和:11
//示例四:过滤拼接
concat = Stream.of("a", "B", "c", "D", "e", "F")
.filter(x -> x.compareTo("Z") > 0)
.reduce("", String::concat);
System.out.println("过滤和字符串连接:" + concat);
//过滤和字符串连接:ace
groupingBy/partitioningBy使用
groupingBy:分组排序
partitioningBy:分区排序
// 示例一:分组排序
Map<Integer, List<User>> personGroups = Stream.generate(new UserSupplier2())
.limit(5)
.collect(Collectors.groupingBy(User::getId));
Iterator it = personGroups.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
System.out.println("id " + persons.getKey() + " = " + persons.getValue());
}
// 通过id进行分组排序:
// id 10 = [{"id":10,"name":"pancm1"}]
// id 11 = [{"id":11,"name":"pancm3"}, {"id":11,"name":"pancm6"}, {"id":11,"name":"pancm4"}, {"id":11,"name":"pancm7"}]
class UserSupplier2 implements Supplier<User> {
private int index = 10;
private Random random = new Random();
@Override
public User get() {
return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
}
return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
}
// 示例二:分区排序
System.out.println("通过年龄进行分区排序:");
Map<Boolean, List<User>> children = Stream.generate(new UserSupplier3())
.limit(5)
.collect(Collectors.partitioningBy(p -> p.getId() < 18));
System.out.println("小孩: " + children.get(true));
System.out.println("成年人: " + children.get(false));
// 通过年龄进行分区排序:
// 小孩: [{"id":16,"name":"pancm7"}, {"id":17,"name":"pancm2"}]
// 成年人: [{"id":18,"name":"pancm4"}, {"id":19,"name":"pancm9"}, {"id":20,"name":"pancm6"}]
class UserSupplier3 implements Supplier<User> {
private int index = 16;
private Random random = new Random();
@Override
public User get() {
return new User(index++, "pancm" + random.nextInt(10));
}
}
List根据某个属性去重
方法一:利用stream构建TreeSet进行去重
cgEndList = cgEndList.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CgModel::getCgId))
), ArrayList::new));
方法二:Predicate断言接口方式进行去重
List<CgDto> result = new ArrayList<>();
endData.stream()
.filter(distinctByKey(CgDto::getCgId))
.forEach(result::add);
static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
//putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。
//如果返回null表示添加数据成功(不重复),不重复(null==null :TRUE)
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
获取ID最大的对象
DyCgExpertDto maxExpertId = dyCgExpertDtos.stream()
.max(Comparator.comparing(DyCgExpertDto::getId)).get();
循环两个list进行条件匹配给其中一个list对象的某个属性赋值
List<CgModel> cgs = cgList.stream()
.map(cg -> nodeInfos.stream()
.filter(node -> cg.getDqjdId().equals(node.getNodeId()))
.findFirst()
.map(node -> {
cg.setNodeName(node.getNodeName());
return cg;
}).orElse(cg))
.collect(Collectors.toList());
合计BigDecimal金额
BigDecimal totalMoney = fkdModelList.stream()
.map(FkdModel::getCountMoney)
.reduce(BigDecimal.ZERO,BigDecimal::add);
交集差集并集
public class Test {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("1");
list1.add("2");
list1.add("3");
list1.add("5");
list1.add("6");
List<String> list2 = new ArrayList<String>();
list2.add("2");
list2.add("3");
list2.add("7");
list2.add("8");
// 交集
List<String> intersection = list1.stream()
.filter(item -> list2.contains(item))
.collect(toList());
System.out.println("---交集 intersection---");
intersection.parallelStream().forEach(System.out :: println);
// 差集 (list1 - list2)
List<String> reduce1 = list1.stream()
.filter(item -> !list2.contains(item))
.collect(toList());
System.out.println("---差集 reduce1 (list1 - list2)---");
reduce1.parallelStream().forEach(System.out :: println);
// 差集 (list2 - list1)
List<String> reduce2 = list2.stream()
.filter(item -> !list1.contains(item))
.collect(toList());
System.out.println("---差集 reduce2 (list2 - list1)---");
reduce2.parallelStream().forEach(System.out :: println);
// 并集
List<String> listAll = list1.parallelStream().collect(toList());
List<String> listAll2 = list2.parallelStream().collect(toList());
listAll.addAll(listAll2);
System.out.println("---并集 listAll---");
listAll.parallelStream().forEachOrdered(System.out :: println);
// 去重并集
List<String> listAllDistinct = listAll.stream()
.distinct()
.collect(toList());
System.out.println("---得到去重并集 listAllDistinct---");
listAllDistinct.parallelStream().forEachOrdered(System.out :: println);
System.out.println("---原来的List1---");
list1.parallelStream().forEachOrdered(System.out :: println);
System.out.println("---原来的List2---");
list2.parallelStream().forEachOrdered(System.out :: println);
}
}
LocalDateTime🤔
全新的日期时间API。在JDK1.8
之前,Java处理日期、日历和时间的方式一直为社区所诟病,将 java.util.Date
设定为可变类型,以及 SimpleDateFormat
的非线程安全
使其应用非常受限。因此推出了java.time
包,该包下的所有类都是不可变类型
而且线程安全
。
关键类
Instant
:瞬时时间。LocalDate
:本地日期,不包含具体时间, 格式yyyy-MM-dd
。LocalTime
:本地时间,不包含日期. 格式yyyy-MM-dd HH:mm:ss.SSS
。LocalDateTime
:组合了日期和时间,但不包含时差和时区信息。ZonedDateTime
:最完整的日期时间,包含时区和相对UTC
或格林威治
的时差。
获取当前的年月日时分秒
//获取当前的时间,包括毫秒
LocalDateTime ldt = LocalDateTime.now();
System.out.println("当前年:"+ldt.getYear());
System.out.println("当前年份天数:"+ldt.getDayOfYear());
System.out.println("当前月:"+ldt.getMonthValue());
System.out.println("当前时:"+ldt.getHour());
System.out.println("当前分:"+ldt.getMinute());
System.out.println("当前时间:"+ldt.toString());
// 输出
// 当前年:2022
// 当前年份天数:61
// 当前月:3
// 当前时:15
// 当前分:25
// 当前时间:2022-03-02T15:25:32.818
格式化时间
LocalDateTime ldt = LocalDateTime.now();
System.out.println("格式化时间: " +
ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
// 格式化时间: 2022-03-02 15:25:32.818
时间增减
LocalDateTime ldt = LocalDateTime.now();
System.out.println("后5天时间:"+ldt.plusDays(5));
System.out.println("前5天时间并格式化:"
+ldt.minusDays(5).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
System.out.println("前一个月的时间:"
+ldt.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyyMM")));
System.out.println("后一个月的时间:"
+ldt.plusMonths(1));
System.out.println("指定2099年的当前时间:"+ldt.withYear(2099));
//输出
// 后5天时间:2022-03-07T15:25:32.818
// 前5天时间并格式化:2022-02-25
// 前一个月的时间:202202
// 后一个月的时间:2022-04-02T15:25:32.818
// 指定2099年的当前时间:2099-03-02T15:25:32.818
创建指定时间
LocalDate ld3=LocalDate.of(2019, Month.NOVEMBER, 17);
LocalDate ld4=LocalDate.of(2022, 02, 11);
System.out.println(ld3);
System.out.println(ld4);
// 输出
// 2019-11-17
// 2022-02-11
时间相差比较
// 示例一: 具体相差的年月日
LocalDate ld=LocalDate.parse("2021-11-17");
LocalDate ld2=LocalDate.parse("2022-01-05");
Period p=Period.between(ld, ld2);
System.out.println("相差年: "+p.getYears()+
" 相差月 :"+p.getMonths() +
" 相差天:"+p.getDays());
// 相差年: 0 相差月 :1 相差天:19
// 注:这里的月份是不满足一年,天数是不满足一个月的。这里实际相差的是1月19天,也就是49天。
// 示例二:相差总数的时间
LocalDate startDate = LocalDate.of(2021, 11, 17);
LocalDate endDate = LocalDate.of(2022, 01, 05);
System.out.println("相差月份:"+ChronoUnit.MONTHS.between(startDate, endDate));
System.out.println("两月之间的相差的天数 : " +
ChronoUnit.DAYS.between(startDate, endDate));
// 相差月份:1
// 两月之间的相差的天数 : 49
// 注:ChronoUnit也可以计算相差时分秒。
// 示例三:精度时间相差
// Duration 这个类以秒和纳秒为单位建模时间的数量或数量。
Instant inst1 = Instant.now();
System.out.println("当前时间戳 : " + inst1);
Instant inst2 = inst1.plus(Duration.ofSeconds(10));
System.out.println("增加之后的时间 : " + inst2);
System.out.println("相差毫秒 : " + Duration.between(inst1, inst2).toMillis());
System.out.println("相毫秒 : " + Duration.between(inst1, inst2).getSeconds());
// 输出
// 当前时间戳 : 2022-03-02T07:30:35.261Z
// 增加之后的时间 : 2022-03-02T07:30:45.261Z
// 相差毫秒 : 10000
// 相毫秒 : 10
// 示例四:时间大小比较
LocalDateTime ldt4 = LocalDateTime.now();
LocalDateTime ldt5 = ldt4.plusMinutes(10);
System.out.println("当前时间是否大于:"+ldt4.isAfter(ldt5));
System.out.println("当前时间是否小于"+ldt4.isBefore(ldt5));
// 当前时间是否大于:false
// 当前时间是否小于true
时区时间计算
// 示例一:通过Clock时钟类获取计算
// Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。
Clock clock = Clock.systemUTC();
System.out.println("当前时间戳 : " + clock.millis());
Clock clock2 = Clock.system(ZoneId.of("Asia/Shanghai"));
System.out.println("亚洲上海此时的时间戳:"+clock2.millis());
Clock clock3 = Clock.system(ZoneId.of("America/New_York"));
System.out.println("美国纽约此时的时间戳:"+clock3.millis());
// 当前时间戳 : 1646206235265
// 亚洲上海此时的时间戳:1646206235265
// 美国纽约此时的时间戳:1646206235266
// 示例二:通过ZonedDateTime类和ZoneId
ZoneId zoneId= ZoneId.of("America/New_York");
ZonedDateTime dateTime=ZonedDateTime.now(zoneId);
System.out.println("美国纽约此时的时间 : " +
dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
System.out.println("美国纽约此时的时间 和时区: " + dateTime);
// 输出
// 美国纽约此时的时间 : 2022-03-02 02:30:35.266
// 美国纽约此时的时间 和时区: 2022-03-02T02:30:35.266-05:00[America/New_York]
一些代码合集
去重且属性值相加
- 1、根据某个属性去重并相同属性的其他属性值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Data> dataList = new ArrayList<>();
// 添加一些测试数据
dataList.add(new Data("A", 10));
dataList.add(new Data("B", 20));
dataList.add(new Data("A", 30));
dataList.add(new Data("C", 40));
dataList.add(new Data("B", 50));
// 根据属性值去重,并将另一个属性值相加
List<Data> distinctList = dataList.stream()
.collect(Collectors.toMap(Data::getProperty, // 根据属性值作为key
data -> data, // 保留原始对象
(data1, data2) -> new Data(data1.getProperty(), data1.getValue() + data2.getValue()))) // 相同属性值的其他属性值相加
.values().stream()
.collect(Collectors.toList());
// 打印结果
for (Data data : distinctList) {
System.out.println(data.getProperty() + " - " + data.getValue());
}
}
}
class Data {
private String property;
private int value;
public Data(String property, int value) {
this.property = property;
this.value = value;
}
public String getProperty() {
return property;
}
public int getValue() {
return value;
}
}
- 2、根据某个属性去重并根据相同属性将多个属性的值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Data> dataList = new ArrayList<>();
// 添加一些测试数据
dataList.add(new Data("A", 10, 1));
dataList.add(new Data("B", 20, 2));
dataList.add(new Data("A", 30, 3));
dataList.add(new Data("C", 40, 4));
dataList.add(new Data("B", 50, 5));
// 根据属性值去重,并根据相同属性将多个属性的值相加
List<Data> distinctList = dataList.stream()
.collect(Collectors.toMap(Data::getProperty, // 根据属性值作为key
data -> data, // 保留原始对象
(data1, data2) -> {
data1.setValue1(data1.getValue1() + data2.getValue1()); // 将属性1相加
data1.setValue2(data1.getValue2() + data2.getValue2()); // 将属性2相加
return data1;
}))
.values().stream()
.collect(Collectors.toList());
// 打印结果
for (Data data : distinctList) {
System.out.println(data.getProperty() + " - " + data.getValue1() + " - " + data.getValue2());
}
}
}
class Data {
private String property;
private int value1;
private int value2;
public Data(String property, int value1, int value2) {
this.property = property;
this.value1 = value1;
this.value2 = value2;
}
public String getProperty() {
return property;
}
public int getValue1() {
return value1;
}
public void setValue1(int value1) {
this.value1 = value1;
}
public int getValue2() {
return value2;
}
public void setValue2(int value2) {
this.value2 = value2;
}
}
- 3、根据多个属性去重并根据相同属性将多个属性的值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Data> dataList = new ArrayList<>();
// 添加一些测试数据
dataList.add(new Data("A", "X", 10));
dataList.add(new Data("B", "Y", 20));
dataList.add(new Data("A", "X", 30));
dataList.add(new Data("C", "Z", 40));
dataList.add(new Data("B", "Y", 50));
// 根据多个属性去重,并根据相同属性将多个属性的值相加
List<Data> distinctList = new ArrayList<>(dataList.stream()
.collect(Collectors.toMap(data -> new Key(data.getProperty1(), data.getProperty2()), // 根据多个属性作为key
data -> data, // 保留原始对象
(data1, data2) -> {
data1.setValue(data1.getValue() + data2.getValue()); // 将属性值相加
return data1;
}))
.values());
// 打印结果
for (Data data : distinctList) {
System.out.println(data.getProperty1() + " - " + data.getProperty2() + " - " + data.getValue());
}
}
}
class Data {
private String property1;
private String property2;
private int value;
public Data(String property1, String property2, int value) {
this.property1 = property1;
this.property2 = property2;
this.value = value;
}
public String getProperty1() {
return property1;
}
public String getProperty2() {
return property2;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
class Key {
private String property1;
private String property2;
public Key(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
@Override
public int hashCode() {
return property1.hashCode() + property2.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Key key = (Key) obj;
return property1.equals(key.property1) && property2.equals(key.property2);
}
}