JAVA8新特性(Stream API,LocalDate,LocalDateTime)

一. Stream API

1.1 基础
代码参数准备:
package com.weige.javaskillpoint.controller;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class JAVA8 {
@Data
static class User {
// 姓名
private String name;
// 手机号
private String phone;
// 年龄
private Integer age;
public User(String name, String phone, Integer age) {
this.name = name;
this.phone = phone;
this.age = age;
}
}
private static List<User> getUserList() {
return new ArrayList<User>() {{
add(new User("周润发", "166", 52));
add(new User("周星驰", "155", 42));
add(new User("刘德华", "177", 62));
add(new User("伍佰", "188", 45));
add(new User("周传雄", "133", 40));
add(new User("甄子丹", "199", 45));
}};
}
}
package com.weige.javaskillpoint.controller;





import lombok.Data;


import lombok.extern.slf4j.Slf4j;





import java.util.ArrayList;


import java.util.List;


import java.util.stream.Collectors;
@Slf4j
public class JAVA8 {

    @Data
    static class User {
        // 姓名
        private String name;
        // 手机号
        private String phone;
        // 年龄
        private Integer age;

        public User(String name, String phone, Integer age) {
            this.name = name;
            this.phone = phone;
            this.age = age;
        }


    }



    private static List<User> getUserList() {
        return new ArrayList<User>() {{
            add(new User("周润发", "166", 52));
            add(new User("周星驰", "155", 42));
            add(new User("刘德华", "177", 62));
            add(new User("伍佰", "188", 45));
            add(new User("周传雄", "133", 40));
            add(new User("甄子丹", "199", 45));
        }};
    }

}
package com.weige.javaskillpoint.controller; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @Slf4j public class JAVA8 { @Data static class User { // 姓名 private String name; // 手机号 private String phone; // 年龄 private Integer age; public User(String name, String phone, Integer age) { this.name = name; this.phone = phone; this.age = age; } } private static List<User> getUserList() { return new ArrayList<User>() {{ add(new User("周润发", "166", 52)); add(new User("周星驰", "155", 42)); add(new User("刘德华", "177", 62)); add(new User("伍佰", "188", 45)); add(new User("周传雄", "133", 40)); add(new User("甄子丹", "199", 45)); }}; } }

场景一:知道一个List对象,如何获取List的所有用户id?
public static void main(String[] args) {
// 知道一个List<User>对象,如何获取List<User>的所有用户手机号?
List<User> userList = getUserList();
List<String> phoneList = userList.stream().map(User::getPhone).collect(Collectors.toList());
// 打印内容 - 所有用户手机号为 [166, 155, 177, 188, 133, 199]
log.info("所有用户手机号为 " + phoneList);
}
    public static void main(String[] args) {

        // 知道一个List<User>对象,如何获取List<User>的所有用户手机号?
        List<User> userList = getUserList();


        List<String> phoneList = userList.stream().map(User::getPhone).collect(Collectors.toList());
        // 打印内容 - 所有用户手机号为 [166, 155, 177, 188, 133, 199]
        log.info("所有用户手机号为 " + phoneList);
    }
public static void main(String[] args) { // 知道一个List<User>对象,如何获取List<User>的所有用户手机号? List<User> userList = getUserList(); List<String> phoneList = userList.stream().map(User::getPhone).collect(Collectors.toList()); // 打印内容 - 所有用户手机号为 [166, 155, 177, 188, 133, 199] log.info("所有用户手机号为 " + phoneList); }

场景二:知道一个List对象,如何获取List中年龄大于50的用户?
public static void main(String[] args) {
// 知道一个List<User>对象,如何获取List<User>中年龄大于50的用户?
List<User> userList = getUserList();
List<User> filterUserList = userList.stream().filter(u -> u.getAge() > 50).collect(Collectors.toList());
// 打印内容 - 年龄大于50的用户为 [JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]
log.info("年龄大于50的用户为 " + filterUserList);
}
    public static void main(String[] args) {

        // 知道一个List<User>对象,如何获取List<User>中年龄大于50的用户?
        List<User> userList = getUserList();


        List<User> filterUserList = userList.stream().filter(u -> u.getAge() > 50).collect(Collectors.toList());
        // 打印内容 - 年龄大于50的用户为 [JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]
        log.info("年龄大于50的用户为 " + filterUserList);
    }
public static void main(String[] args) { // 知道一个List<User>对象,如何获取List<User>中年龄大于50的用户? List<User> userList = getUserList(); List<User> filterUserList = userList.stream().filter(u -> u.getAge() > 50).collect(Collectors.toList()); // 打印内容 - 年龄大于50的用户为 [JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)] log.info("年龄大于50的用户为 " + filterUserList); }

场景三:知道一个List对象,如何按照年龄从小到小排序,从大到小排序?
public static void main(String[] args) {
// 知道一个List<User>对象,如何按照年龄从大到小排序?
List<User> userList = getUserList();
List<User> ascUserList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
List<User> reversedUserList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
// 打印内容 - 年龄从小到大 [JAVA8.User(name=周传雄, phone=133, age=40), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]
log.info("年龄从小到大 " + ascUserList);
// 打印内容 - 年龄从大到小 [JAVA8.User(name=刘德华, phone=177, age=62), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=周传雄, phone=133, age=40)]
log.info("年龄从大到小 " + reversedUserList);
}
public static void main(String[] args) {
        // 知道一个List<User>对象,如何按照年龄从大到小排序?
        List<User> userList = getUserList();


        List<User> ascUserList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
        List<User> reversedUserList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
        // 打印内容 - 年龄从小到大 [JAVA8.User(name=周传雄, phone=133, age=40), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)]
        log.info("年龄从小到大 " + ascUserList);
        // 打印内容 - 年龄从大到小 [JAVA8.User(name=刘德华, phone=177, age=62), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=周传雄, phone=133, age=40)]
        log.info("年龄从大到小 " + reversedUserList);
    }
public static void main(String[] args) { // 知道一个List<User>对象,如何按照年龄从大到小排序? List<User> userList = getUserList(); List<User> ascUserList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList()); List<User> reversedUserList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList()); // 打印内容 - 年龄从小到大 [JAVA8.User(name=周传雄, phone=133, age=40), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=刘德华, phone=177, age=62)] log.info("年龄从小到大 " + ascUserList); // 打印内容 - 年龄从大到小 [JAVA8.User(name=刘德华, phone=177, age=62), JAVA8.User(name=周润发, phone=166, age=52), JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45), JAVA8.User(name=周星驰, phone=155, age=42), JAVA8.User(name=周传雄, phone=133, age=40)] log.info("年龄从大到小 " + reversedUserList); }

场景四:知道一个List对象,如何按照相同年龄进行分组,并获取分组后的数量?
public static void main(String[] args) {
// 知道一个List<User>对象,如何按照相同年龄进行分组?
List<User> userList = getUserList();
Map<Integer, List<User>> groupingUserList = userList.stream().collect(Collectors.groupingBy(User::getAge));
// 打印内容 - 相同年龄进行分组 {52=[JAVA8.User(name=周润发, phone=166, age=52)], 40=[JAVA8.User(name=周传雄, phone=133, age=40)], 42=[JAVA8.User(name=周星驰, phone=155, age=42)], 45=[JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45)], 62=[JAVA8.User(name=刘德华, phone=177, age=62)]}
log.info("相同年龄进行分组 " + groupingUserList);
// 知道一个List<User>对象,如何按照相同年龄进行分组后获取其对应数量?
Map<Integer, Long> countUserList = userList.stream().collect(Collectors.groupingBy(User::getAge, Collectors.counting()));
// 打印内容 - 相同年龄进行分组的数量 {52=1, 40=1, 42=1, 45=2, 62=1}
log.info("相同年龄进行分组的数量 " + countUserList);
}
public static void main(String[] args) {
        // 知道一个List<User>对象,如何按照相同年龄进行分组?
        List<User> userList = getUserList();
        Map<Integer, List<User>> groupingUserList = userList.stream().collect(Collectors.groupingBy(User::getAge));
        // 打印内容 - 相同年龄进行分组 {52=[JAVA8.User(name=周润发, phone=166, age=52)], 40=[JAVA8.User(name=周传雄, phone=133, age=40)], 42=[JAVA8.User(name=周星驰, phone=155, age=42)], 45=[JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45)], 62=[JAVA8.User(name=刘德华, phone=177, age=62)]}
        log.info("相同年龄进行分组 " + groupingUserList);
        // 知道一个List<User>对象,如何按照相同年龄进行分组后获取其对应数量?
        Map<Integer, Long> countUserList = userList.stream().collect(Collectors.groupingBy(User::getAge, Collectors.counting()));
        // 打印内容 - 相同年龄进行分组的数量 {52=1, 40=1, 42=1, 45=2, 62=1}
        log.info("相同年龄进行分组的数量 " + countUserList);
    }
public static void main(String[] args) { // 知道一个List<User>对象,如何按照相同年龄进行分组? List<User> userList = getUserList(); Map<Integer, List<User>> groupingUserList = userList.stream().collect(Collectors.groupingBy(User::getAge)); // 打印内容 - 相同年龄进行分组 {52=[JAVA8.User(name=周润发, phone=166, age=52)], 40=[JAVA8.User(name=周传雄, phone=133, age=40)], 42=[JAVA8.User(name=周星驰, phone=155, age=42)], 45=[JAVA8.User(name=伍佰, phone=188, age=45), JAVA8.User(name=甄子丹, phone=199, age=45)], 62=[JAVA8.User(name=刘德华, phone=177, age=62)]} log.info("相同年龄进行分组 " + groupingUserList); // 知道一个List<User>对象,如何按照相同年龄进行分组后获取其对应数量? Map<Integer, Long> countUserList = userList.stream().collect(Collectors.groupingBy(User::getAge, Collectors.counting())); // 打印内容 - 相同年龄进行分组的数量 {52=1, 40=1, 42=1, 45=2, 62=1} log.info("相同年龄进行分组的数量 " + countUserList); }

1.2 进阶
场景一:有一张用户浏览记录表,一个用户可以有多条浏览记录,且有不同的浏览类型;比如小明浏览娱乐模块530秒,浏览军事模块600秒,则对应两个浏览记录数据。新建用户浏览类型统计表,根据现有的用户浏览记录表数据对用户浏览类型统计表进行新增,请用Stream优雅的实现该功能?
package com.weige.javaskillpoint.controller;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class JAVA8 {
@Data
static class History {
// 用户id
private Long userId;
// 用户浏览类型 (1->娱乐 2->军事 3->教育)
private Integer type;
// 用户浏览时间(单位秒)
private Long seconds;
public History(Long userId, Integer type, Long seconds) {
this.userId = userId;
this.type = type;
this.seconds = seconds;
}
}
@Data
static class HistoryStatistics {
// 用户id
private Long userId;
// 用户浏览类型 (1->娱乐 2->军事 3->教育)
private Integer type;
// 浏览类型统计数量
private Long count;
public HistoryStatistics(Long userId, Integer type, Long count) {
this.userId = userId;
this.type = type;
this.count = count;
}
}
public static void main(String[] args) {
// 模拟用户浏览记录数据
List<History> historyList = new ArrayList<History>() {
{
add(new History(20231L, 1, 360L));
add(new History(20231L, 1, 720L));
add(new History(20231L, 2, 1360L));
add(new History(20231L, 2, 2360L));
add(new History(20239L, 2, 2360L));
add(new History(20239L, 3, 360L));
add(new History(20233L, 3, 360L));
}
};
List<HistoryStatistics> insertHistoryStatisticsList = new ArrayList<>();
// 根据用户id进行分组
Map<Long, List<History>> groupingByUserIdMap = historyList.stream().collect(Collectors.groupingBy(History::getUserId));
groupingByUserIdMap.forEach((key, value) -> {
Map<Integer, Long> countMap = historyList.stream()
// 筛选出对应用户id的浏览记录
.filter(h -> key.equals(h.getUserId()))
// 对用户id的浏览记录根据类型进行分组并获取数量
.collect(Collectors.groupingBy(History::getType, Collectors.counting()));
// 将用户浏览记录类型分组的数量Map转成List<HistoryStatistics>
List<HistoryStatistics> historyStatisticsList = countMap.entrySet().stream().map(u -> new HistoryStatistics(key, u.getKey(), u.getValue())).collect(Collectors.toList());
insertHistoryStatisticsList.addAll(historyStatisticsList);
});
// 批量新增用户浏览记录统计表
batchInsertHistoryStatistics(insertHistoryStatisticsList);
}
public static void batchInsertHistoryStatistics(List<HistoryStatistics> insertHistoryStatisticsList) {
log.info("------连接数据库------");
log.info("------开始批量新增数据------");
log.info("------批量新增数据: " + insertHistoryStatisticsList);
log.info("------批量新增数据结束------");
log.info("------关闭数据库连接------");
}
}
package com.weige.javaskillpoint.controller;





import lombok.Data;


import lombok.extern.slf4j.Slf4j;





import java.util.ArrayList;


import java.util.List;


import java.util.Map;

import java.util.stream.Collectors;





@Slf4j

public class JAVA8 {



    @Data

    static class History {

        // 用户id
        private Long userId;
        // 用户浏览类型 (1->娱乐 2->军事 3->教育)

        private Integer type;

        // 用户浏览时间(单位秒)

        private Long seconds;



        public History(Long userId, Integer type, Long seconds) {
            this.userId = userId;
            this.type = type;

            this.seconds = seconds;

        }

    }



    @Data
    static class HistoryStatistics {
        // 用户id
        private Long userId;
        // 用户浏览类型 (1->娱乐 2->军事 3->教育)
        private Integer type;
        // 浏览类型统计数量
        private Long count;


        public HistoryStatistics(Long userId, Integer type, Long count) {
            this.userId = userId;
            this.type = type;
            this.count = count;
        }
    }

    public static void main(String[] args) {
        // 模拟用户浏览记录数据
        List<History> historyList = new ArrayList<History>() {
            {
                add(new History(20231L, 1, 360L));
                add(new History(20231L, 1, 720L));
                add(new History(20231L, 2, 1360L));
                add(new History(20231L, 2, 2360L));
                add(new History(20239L, 2, 2360L));
                add(new History(20239L, 3, 360L));
                add(new History(20233L, 3, 360L));
            }
        };

        List<HistoryStatistics> insertHistoryStatisticsList = new ArrayList<>();

        // 根据用户id进行分组
        Map<Long, List<History>> groupingByUserIdMap = historyList.stream().collect(Collectors.groupingBy(History::getUserId));

        groupingByUserIdMap.forEach((key, value) -> {
            Map<Integer, Long> countMap = historyList.stream()
                    // 筛选出对应用户id的浏览记录
                    .filter(h -> key.equals(h.getUserId()))
                    // 对用户id的浏览记录根据类型进行分组并获取数量
                    .collect(Collectors.groupingBy(History::getType, Collectors.counting()));

            // 将用户浏览记录类型分组的数量Map转成List<HistoryStatistics>
            List<HistoryStatistics> historyStatisticsList = countMap.entrySet().stream().map(u -> new HistoryStatistics(key, u.getKey(), u.getValue())).collect(Collectors.toList());
            insertHistoryStatisticsList.addAll(historyStatisticsList);
        });

        // 批量新增用户浏览记录统计表
        batchInsertHistoryStatistics(insertHistoryStatisticsList);
    }


    public static void batchInsertHistoryStatistics(List<HistoryStatistics> insertHistoryStatisticsList) {
        log.info("------连接数据库------");
        log.info("------开始批量新增数据------");
        log.info("------批量新增数据: " + insertHistoryStatisticsList);
        log.info("------批量新增数据结束------");
        log.info("------关闭数据库连接------");
    }
}
package com.weige.javaskillpoint.controller; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Slf4j public class JAVA8 { @Data static class History { // 用户id private Long userId; // 用户浏览类型 (1->娱乐 2->军事 3->教育) private Integer type; // 用户浏览时间(单位秒) private Long seconds; public History(Long userId, Integer type, Long seconds) { this.userId = userId; this.type = type; this.seconds = seconds; } } @Data static class HistoryStatistics { // 用户id private Long userId; // 用户浏览类型 (1->娱乐 2->军事 3->教育) private Integer type; // 浏览类型统计数量 private Long count; public HistoryStatistics(Long userId, Integer type, Long count) { this.userId = userId; this.type = type; this.count = count; } } public static void main(String[] args) { // 模拟用户浏览记录数据 List<History> historyList = new ArrayList<History>() { { add(new History(20231L, 1, 360L)); add(new History(20231L, 1, 720L)); add(new History(20231L, 2, 1360L)); add(new History(20231L, 2, 2360L)); add(new History(20239L, 2, 2360L)); add(new History(20239L, 3, 360L)); add(new History(20233L, 3, 360L)); } }; List<HistoryStatistics> insertHistoryStatisticsList = new ArrayList<>(); // 根据用户id进行分组 Map<Long, List<History>> groupingByUserIdMap = historyList.stream().collect(Collectors.groupingBy(History::getUserId)); groupingByUserIdMap.forEach((key, value) -> { Map<Integer, Long> countMap = historyList.stream() // 筛选出对应用户id的浏览记录 .filter(h -> key.equals(h.getUserId())) // 对用户id的浏览记录根据类型进行分组并获取数量 .collect(Collectors.groupingBy(History::getType, Collectors.counting())); // 将用户浏览记录类型分组的数量Map转成List<HistoryStatistics> List<HistoryStatistics> historyStatisticsList = countMap.entrySet().stream().map(u -> new HistoryStatistics(key, u.getKey(), u.getValue())).collect(Collectors.toList()); insertHistoryStatisticsList.addAll(historyStatisticsList); }); // 批量新增用户浏览记录统计表 batchInsertHistoryStatistics(insertHistoryStatisticsList); } public static void batchInsertHistoryStatistics(List<HistoryStatistics> insertHistoryStatisticsList) { log.info("------连接数据库------"); log.info("------开始批量新增数据------"); log.info("------批量新增数据: " + insertHistoryStatisticsList); log.info("------批量新增数据结束------"); log.info("------关闭数据库连接------"); } }

场景二:有一张用户浏览记录表,一个用户可以有多条浏览记录,且有不同的浏览类型;比如小明浏览娱乐模块530秒,浏览军事模块600秒;小红浏览娱乐模块1000秒,浏览军事模块100秒,则对应四条浏览记录数据。想要得到每个用户总共的浏览时长,请用Stream优雅的实现该功能?
package com.weige.javaskillpoint.controller;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class JAVA8 {
@Data
static class History {
// 用户姓名
private String userName;
// 用户浏览类型 (1->娱乐 2->军事 3->教育)
private Integer type;
// 用户浏览时间(单位秒)
private Long seconds;
public History(String userName, Integer type, Long seconds) {
this.userName = userName;
this.type = type;
this.seconds = seconds;
}
}
public static void main(String[] args) {
List<History> historyList = new ArrayList<History>() {
{
add(new History("小明", 1, 360L));
add(new History("小明", 1, 720L));
add(new History("小明", 2, 1360L));
add(new History("小明", 2, 2360L));
add(new History("小红", 2, 2360L));
add(new History("小白", 3, 360L));
add(new History("小红", 3, 360L));
add(new History("小白", 3, 1060L));
}
};
// 串行流中reduce的第三个参数combiner无作用 返回值可以写为null
HashMap<String, Long> reduce = historyList.stream().reduce(new HashMap<>(), (m, e) -> {
m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());
return m;
}, (m1,m2) -> null);
// 返回结果 - {小明=4800, 小白=1420, 小红=2720}
log.info("数据为: " + reduce);
// 并行流中reduce的第三个参数combiner有作用 如果返回结果为map 则应用putAll()来解决并发情况下数据不一致问题 同时返回值应用ConcurrentHashMap接收
ConcurrentHashMap<String, Long> parallelReduce = historyList.stream().parallel().reduce(new ConcurrentHashMap<>(), (m, e) -> {
m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());
return m;
}, (m1,m2) -> {
m1.putAll(m2);
return m1;
});
// 返回结果 - {小明=4800, 小白=1420, 小红=2720}
log.info("数据为: " + parallelReduce);
// 这里举个例子:如果reduce第一个参数为1,则stream执行时,分两个阶段;
// 第一个阶段分3步:1 + 1 = 2,1 + 2 = 3,1 + 3 = 4;
// 第二个阶段 2 * 3 * 4 = 24
List<Integer> intList = new ArrayList<Integer>(){{
add(1);
add(2);
add(3);
}};
Integer sum = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
}, (integer, integer2) -> integer * integer2);
// 返回结果 - 并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): 24
log.info("并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): " + sum);
Integer multipliers = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
});
// 返回结果 - 并行流中第三个参数返回自己本身,不进行任何操作: 9
log.info("并行流中第三个参数返回自己本身,不进行任何操作: " + multipliers);
Integer num = intList.stream().reduce(1,Integer::sum);
// 返回结果 - 串行流不使用第三个参数 7
log.info("串行流不使用第三个参数 " + num);
}
}
package com.weige.javaskillpoint.controller;





import lombok.Data;


import lombok.extern.slf4j.Slf4j;





import java.util.ArrayList;


import java.util.List;


import java.util.Map;

import java.util.stream.Collectors;





@Slf4j

public class JAVA8 {



    @Data

    static class History {

        // 用户姓名
        private String userName;
        // 用户浏览类型 (1->娱乐 2->军事 3->教育)

        private Integer type;

        // 用户浏览时间(单位秒)

        private Long seconds;



        public History(String userName, Integer type, Long seconds) {
            this.userName = userName;
            this.type = type;

            this.seconds = seconds;

        }

    }



    public static void main(String[] args) {
        List<History> historyList = new ArrayList<History>() {
            {
                add(new History("小明", 1, 360L));
                add(new History("小明", 1, 720L));
                add(new History("小明", 2, 1360L));
                add(new History("小明", 2, 2360L));
                add(new History("小红", 2, 2360L));
                add(new History("小白", 3, 360L));
                add(new History("小红", 3, 360L));
                add(new History("小白", 3, 1060L));
            }
        };

        // 串行流中reduce的第三个参数combiner无作用 返回值可以写为null
        HashMap<String, Long> reduce = historyList.stream().reduce(new HashMap<>(), (m, e) -> {
            m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());
            return m;
        }, (m1,m2) -> null);
        // 返回结果 - {小明=4800, 小白=1420, 小红=2720}
        log.info("数据为: " + reduce);

        // 并行流中reduce的第三个参数combiner有作用 如果返回结果为map 则应用putAll()来解决并发情况下数据不一致问题 同时返回值应用ConcurrentHashMap接收
        ConcurrentHashMap<String, Long> parallelReduce = historyList.stream().parallel().reduce(new ConcurrentHashMap<>(), (m, e) -> {
            m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds());
            return m;
        }, (m1,m2) -> {
            m1.putAll(m2);
            return m1;
        });
        // 返回结果 - {小明=4800, 小白=1420, 小红=2720}
        log.info("数据为: " + parallelReduce);


        // 这里举个例子:如果reduce第一个参数为1,则stream执行时,分两个阶段;
        // 第一个阶段分3步:1 + 1 = 2,1 + 2 = 3,1 + 3 = 4;
        // 第二个阶段 2 * 3 * 4 = 24
        List<Integer> intList = new ArrayList<Integer>(){{
            add(1);
            add(2);
            add(3);
        }};
        Integer sum = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer + integer2;
            }
        }, (integer, integer2) -> integer * integer2);
        // 返回结果 - 并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): 24
        log.info("并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): " + sum);


        Integer multipliers = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer + integer2;
            }
        });
        // 返回结果 - 并行流中第三个参数返回自己本身,不进行任何操作: 9
        log.info("并行流中第三个参数返回自己本身,不进行任何操作: " + multipliers);

        Integer num = intList.stream().reduce(1,Integer::sum);
        // 返回结果 - 串行流不使用第三个参数 7
        log.info("串行流不使用第三个参数 " + num);
    }
    
}
package com.weige.javaskillpoint.controller; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Slf4j public class JAVA8 { @Data static class History { // 用户姓名 private String userName; // 用户浏览类型 (1->娱乐 2->军事 3->教育) private Integer type; // 用户浏览时间(单位秒) private Long seconds; public History(String userName, Integer type, Long seconds) { this.userName = userName; this.type = type; this.seconds = seconds; } } public static void main(String[] args) { List<History> historyList = new ArrayList<History>() { { add(new History("小明", 1, 360L)); add(new History("小明", 1, 720L)); add(new History("小明", 2, 1360L)); add(new History("小明", 2, 2360L)); add(new History("小红", 2, 2360L)); add(new History("小白", 3, 360L)); add(new History("小红", 3, 360L)); add(new History("小白", 3, 1060L)); } }; // 串行流中reduce的第三个参数combiner无作用 返回值可以写为null HashMap<String, Long> reduce = historyList.stream().reduce(new HashMap<>(), (m, e) -> { m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds()); return m; }, (m1,m2) -> null); // 返回结果 - {小明=4800, 小白=1420, 小红=2720} log.info("数据为: " + reduce); // 并行流中reduce的第三个参数combiner有作用 如果返回结果为map 则应用putAll()来解决并发情况下数据不一致问题 同时返回值应用ConcurrentHashMap接收 ConcurrentHashMap<String, Long> parallelReduce = historyList.stream().parallel().reduce(new ConcurrentHashMap<>(), (m, e) -> { m.put(e.getUserName(), m.getOrDefault(e.getUserName(), 0L) + e.getSeconds()); return m; }, (m1,m2) -> { m1.putAll(m2); return m1; }); // 返回结果 - {小明=4800, 小白=1420, 小红=2720} log.info("数据为: " + parallelReduce); // 这里举个例子:如果reduce第一个参数为1,则stream执行时,分两个阶段; // 第一个阶段分3步:1 + 1 = 2,1 + 2 = 3,1 + 3 = 4; // 第二个阶段 2 * 3 * 4 = 24 List<Integer> intList = new ArrayList<Integer>(){{ add(1); add(2); add(3); }}; Integer sum = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer + integer2; } }, (integer, integer2) -> integer * integer2); // 返回结果 - 并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): 24 log.info("并行流中用第三个参数(类似于函数表达式对参数进行乘法操作): " + sum); Integer multipliers = intList.stream().parallel().reduce(1, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer + integer2; } }); // 返回结果 - 并行流中第三个参数返回自己本身,不进行任何操作: 9 log.info("并行流中第三个参数返回自己本身,不进行任何操作: " + multipliers); Integer num = intList.stream().reduce(1,Integer::sum); // 返回结果 - 串行流不使用第三个参数 7 log.info("串行流不使用第三个参数 " + num); } }

二. LocalDate,LocalDateTime

2.1 基础
一般前端传给后端的时间参数,都是字符串拼接,比如”2023-07-19″,”2023 -07-19 20:00:00″,这都是字符串;而查询数据库时,是需要根据Date时间类型来查询,所以这里需要将字符串转成Date,如果中间需要操作时间(年,月,日,时,分加减)
LocalDate
public static void main(String[] args) {
// 模拟前端传过来的时间参数
String dateString = "2023-07-19";
// 将字符串转成LocalDateTime 这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错
// 2023-07-19 -> yyyy-MM-dd
// LocalDate只能操作年 月 日
LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 减1年
LocalDate minusYears = localDate.minusYears(1);
// 加1年
LocalDate plusYears = localDate.plusYears(1);
// 减1月
LocalDate minusMonths = localDate.minusMonths(1);
// 加1月
LocalDate plusMonths = localDate.plusMonths(1);
// 减1日
LocalDate minusDays = localDate.minusDays(1);
// 加1日
LocalDate plusDays = localDate.plusDays(1);
// 通过LocalDate操作时间参数得到自己想要的结果时 转换成Date类型查询数据库
// LocalDate转Date
Date date = localDateTurnDate(minusYears);
getListByDate(date);
System.out.println(date);
}
public static Date localDateTurnDate(LocalDate localDate) {
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
return Date.from(instant);
}
public static void getListByDate(Date date) {
// 模拟查询结果
ArrayList<String> arrayList = new ArrayList<String>() {{
add("一辈子");
add("下辈子");
}};
System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
}
    public static void main(String[] args) {

        // 模拟前端传过来的时间参数

        String dateString = "2023-07-19";


        // 将字符串转成LocalDateTime  这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错

        // 2023-07-19 -> yyyy-MM-dd
        // LocalDate只能操作年 月 日
        LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 减1年
        LocalDate minusYears = localDate.minusYears(1);
        // 加1年
        LocalDate plusYears = localDate.plusYears(1);
        // 减1月
        LocalDate minusMonths = localDate.minusMonths(1);
        // 加1月
        LocalDate plusMonths = localDate.plusMonths(1);
        // 减1日
        LocalDate minusDays = localDate.minusDays(1);
        // 加1日
        LocalDate plusDays = localDate.plusDays(1);
        // 通过LocalDate操作时间参数得到自己想要的结果时 转换成Date类型查询数据库
        // LocalDate转Date
        Date date = localDateTurnDate(minusYears);
        getListByDate(date);
        System.out.println(date);


    }



    public static Date localDateTurnDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static void getListByDate(Date date) {
        // 模拟查询结果
        ArrayList<String> arrayList = new ArrayList<String>() {{
            add("一辈子");
            add("下辈子");
        }};
        System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
    }
public static void main(String[] args) { // 模拟前端传过来的时间参数 String dateString = "2023-07-19"; // 将字符串转成LocalDateTime 这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错 // 2023-07-19 -> yyyy-MM-dd // LocalDate只能操作年 月 日 LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd")); // 减1年 LocalDate minusYears = localDate.minusYears(1); // 加1年 LocalDate plusYears = localDate.plusYears(1); // 减1月 LocalDate minusMonths = localDate.minusMonths(1); // 加1月 LocalDate plusMonths = localDate.plusMonths(1); // 减1日 LocalDate minusDays = localDate.minusDays(1); // 加1日 LocalDate plusDays = localDate.plusDays(1); // 通过LocalDate操作时间参数得到自己想要的结果时 转换成Date类型查询数据库 // LocalDate转Date Date date = localDateTurnDate(minusYears); getListByDate(date); System.out.println(date); } public static Date localDateTurnDate(LocalDate localDate) { ZoneId zone = ZoneId.systemDefault(); Instant instant = localDate.atStartOfDay().atZone(zone).toInstant(); return Date.from(instant); } public static void getListByDate(Date date) { // 模拟查询结果 ArrayList<String> arrayList = new ArrayList<String>() {{ add("一辈子"); add("下辈子"); }}; System.out.println("根据时间" + date + "查询结果为 : " + arrayList); }

LocalDateTime
public static void main(String[] args) {
// 模拟前端传过来的时间参数
String dateString = "2023-07-19 20:20:20";
// 将字符串转成LocalDateTime 这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错
// 2023-07-19 20:20:20 -> yyyy-MM-dd HH:mm:ss
// 2023-07-19 20:20 -> yyyy-MM-dd HH:mm
// 2023-07-19 -> yyyy-MM-dd
LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 减1年
LocalDateTime minusYears = localDateTime.minusYears(1);
// 加1年
LocalDateTime plusYears = localDateTime.plusYears(1);
// 减1月
LocalDateTime minusMonths = localDateTime.minusMonths(1);
// 加1月
LocalDateTime plusMonths = localDateTime.plusMonths(1);
// 减1日
LocalDateTime minusDays = localDateTime.minusDays(1);
// 加1日
LocalDateTime plusDays = localDateTime.plusDays(1);
// 减1小时
LocalDateTime minusHours = localDateTime.minusHours(1);
// 加1小时
LocalDateTime plusHours = localDateTime.plusHours(1);
// 通过LocalDateTime操作时间参数得到自己想要的结果时 转换成Date类型查询数据库
// LocalDateTime转Date
Date date = localDateTimeTurnDate(minusYears);
getListByDate(date);
System.out.println(date);
}
public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
}
public static void getListByDate(Date date) {
// 模拟查询结果
ArrayList<String> arrayList = new ArrayList<String>() {{
add("一辈子");
add("下辈子");
}};
System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
}
    public static void main(String[] args) {

        // 模拟前端传过来的时间参数

        String dateString = "2023-07-19 20:20:20";


        // 将字符串转成LocalDateTime  这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错

        // 2023-07-19 20:20:20 -> yyyy-MM-dd HH:mm:ss
        // 2023-07-19 20:20 -> yyyy-MM-dd HH:mm
        // 2023-07-19 -> yyyy-MM-dd
        LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        // 减1年
        LocalDateTime minusYears = localDateTime.minusYears(1);
        // 加1年
        LocalDateTime plusYears = localDateTime.plusYears(1);
        // 减1月
        LocalDateTime minusMonths = localDateTime.minusMonths(1);
        // 加1月
        LocalDateTime plusMonths = localDateTime.plusMonths(1);
        // 减1日
        LocalDateTime minusDays = localDateTime.minusDays(1);
        // 加1日
        LocalDateTime plusDays = localDateTime.plusDays(1);
        // 减1小时
        LocalDateTime minusHours = localDateTime.minusHours(1);
        // 加1小时
        LocalDateTime plusHours = localDateTime.plusHours(1);
        // 通过LocalDateTime操作时间参数得到自己想要的结果时 转换成Date类型查询数据库
        // LocalDateTime转Date
        Date date = localDateTimeTurnDate(minusYears);
        getListByDate(date);
        System.out.println(date);

    }

    public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }


    public static void getListByDate(Date date) {
        // 模拟查询结果
        ArrayList<String> arrayList = new ArrayList<String>() {{
            add("一辈子");
            add("下辈子");
        }};
        System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
    }
public static void main(String[] args) { // 模拟前端传过来的时间参数 String dateString = "2023-07-19 20:20:20"; // 将字符串转成LocalDateTime 这里看前端传的时间格式 ofPattern里面对应时间格式 不然会报错 // 2023-07-19 20:20:20 -> yyyy-MM-dd HH:mm:ss // 2023-07-19 20:20 -> yyyy-MM-dd HH:mm // 2023-07-19 -> yyyy-MM-dd LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // 减1年 LocalDateTime minusYears = localDateTime.minusYears(1); // 加1年 LocalDateTime plusYears = localDateTime.plusYears(1); // 减1月 LocalDateTime minusMonths = localDateTime.minusMonths(1); // 加1月 LocalDateTime plusMonths = localDateTime.plusMonths(1); // 减1日 LocalDateTime minusDays = localDateTime.minusDays(1); // 加1日 LocalDateTime plusDays = localDateTime.plusDays(1); // 减1小时 LocalDateTime minusHours = localDateTime.minusHours(1); // 加1小时 LocalDateTime plusHours = localDateTime.plusHours(1); // 通过LocalDateTime操作时间参数得到自己想要的结果时 转换成Date类型查询数据库 // LocalDateTime转Date Date date = localDateTimeTurnDate(minusYears); getListByDate(date); System.out.println(date); } public static Date localDateTimeTurnDate(LocalDateTime localDateTime) { Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); return Date.from(instant); } public static void getListByDate(Date date) { // 模拟查询结果 ArrayList<String> arrayList = new ArrayList<String>() {{ add("一辈子"); add("下辈子"); }}; System.out.println("根据时间" + date + "查询结果为 : " + arrayList); }

2.2 进阶
对时间参数进行比较
通过当前时间,查询前6个小时数据库的数据
public static void main(String[] args) {
// 近6个小时
String format = DateUtils.format(new Date(), "yyyy-MM-dd HH");
LocalDateTime now = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
for (LocalDateTime currentdate = now.minusHours(5); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusHours(1)) {
Date date = localDateTimeTurnDate(currentdate);
getListByDate(date);
}
}
public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
}
public static void getListByDate(Date date) {
// 模拟查询结果
ArrayList<String> arrayList = new ArrayList<String>() {{
add("一辈子");
add("下辈子");
}};
System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
}
    public static void main(String[] args) {

        // 近6个小时
        String format = DateUtils.format(new Date(), "yyyy-MM-dd HH");
        LocalDateTime now = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
        for (LocalDateTime currentdate = now.minusHours(5); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusHours(1)) {
            Date date = localDateTimeTurnDate(currentdate);

            getListByDate(date);

        }

    }





    public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {

        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();

        return Date.from(instant);

    }

    
    public static void getListByDate(Date date) {
        // 模拟查询结果
        ArrayList<String> arrayList = new ArrayList<String>() {{
            add("一辈子");
            add("下辈子");
        }};
        System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
    }
public static void main(String[] args) { // 近6个小时 String format = DateUtils.format(new Date(), "yyyy-MM-dd HH"); LocalDateTime now = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH")); for (LocalDateTime currentdate = now.minusHours(5); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusHours(1)) { Date date = localDateTimeTurnDate(currentdate); getListByDate(date); } } public static Date localDateTimeTurnDate(LocalDateTime localDateTime) { Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); return Date.from(instant); } public static void getListByDate(Date date) { // 模拟查询结果 ArrayList<String> arrayList = new ArrayList<String>() {{ add("一辈子"); add("下辈子"); }}; System.out.println("根据时间" + date + "查询结果为 : " + arrayList); }

通过当前时间,查询近7天数据库的数据
public static void main(String[] args) {
// 近7天
String format = DateUtils.format(new Date(), "yyyy-MM-dd");
LocalDateTime now = LocalDate.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
for (LocalDateTime currentdate = now.minusDays(6); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusDays(1)) {
Date date = localDateTimeTurnDate(currentdate);
getListByDate(date);
}
}
public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
}
public static void getListByDate(Date date) {
// 模拟查询结果
ArrayList<String> arrayList = new ArrayList<String>() {{
add("一辈子");
add("下辈子");
}};
System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
}
    public static void main(String[] args) {

        // 近7天
        String format = DateUtils.format(new Date(), "yyyy-MM-dd");
        LocalDateTime now = LocalDate.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
        for (LocalDateTime currentdate = now.minusDays(6); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusDays(1)) {
            Date date = localDateTimeTurnDate(currentdate);

            getListByDate(date);

        }

    }





    public static Date localDateTimeTurnDate(LocalDateTime localDateTime) {

        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();

        return Date.from(instant);

    }



    public static void getListByDate(Date date) {
        // 模拟查询结果
        ArrayList<String> arrayList = new ArrayList<String>() {{
            add("一辈子");
            add("下辈子");
        }};
        System.out.println("根据时间" + date + "查询结果为 : " + arrayList);
    }
public static void main(String[] args) { // 近7天 String format = DateUtils.format(new Date(), "yyyy-MM-dd"); LocalDateTime now = LocalDate.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay(); for (LocalDateTime currentdate = now.minusDays(6); currentdate.isBefore(now) || currentdate.isEqual(now); currentdate = currentdate.plusDays(1)) { Date date = localDateTimeTurnDate(currentdate); getListByDate(date); } } public static Date localDateTimeTurnDate(LocalDateTime localDateTime) { Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); return Date.from(instant); } public static void getListByDate(Date date) { // 模拟查询结果 ArrayList<String> arrayList = new ArrayList<String>() {{ add("一辈子"); add("下辈子"); }}; System.out.println("根据时间" + date + "查询结果为 : " + arrayList); }

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYZFnu2C' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片