基于流java 8中的group by的最大值或最小值

基于流java 8中的group by的最大值或最小值,java,java-8,java-stream,Java,Java 8,Java Stream,与前面回答的问题类似: 但事实并非如此 我有一个有三列的表: LogId、开始时间、结束时间 现在我们有多个相同LogId的条目,它们的开始时间和结束时间不同 问题是: 我所有的列都是字符串,所以如何根据它们的值计算任何列的最小值或最大值 我需要通过登录到单个流中来找出min(StartTime)、max(EndTime)组 如何在Java8中使用流以最少的代码和最大的效率实现这一点 随附的是示例类: public class Log { private static final

与前面回答的问题类似:

但事实并非如此

我有一个有三列的表:
LogId、开始时间、结束时间

现在我们有多个相同LogId的条目,它们的开始时间和结束时间不同

问题是:

  • 我所有的列都是字符串,所以如何根据它们的值计算任何列的最小值或最大值

  • 我需要通过登录到单个流中来找出min(StartTime)、max(EndTime)组


  • 如何在Java8中使用流以最少的代码和最大的效率实现这一点

    随附的是示例类:

    public class Log {  
    
        private static final String inputFileName = "D:\\path\\to\\Log.csv";
    
        private static final String outputFileName = "D:\\path\\to\\Output\\Log.csv";
    
        private static List<Log> logList = null;
    
        private static Map<String, List<Log>> groupByLogId = new HashMap<String, List<Log>>();
    
        private String log_Id;
        private String startTime;
        private String endTime;
    
        public static Map<String, List<Log>> createLogMap() throws IOException {
            Function<String, Log> mapToLog = (line) -> {
                String[] p = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
                Log log = new Log(p[0],p[1],
                        p[2]);
    
                return log;
            };
    
    
            InputStream is = null;
            BufferedReader br = null;
    
                is = new FileInputStream(new File(inputFileName));
    
                br = new BufferedReader(new InputStreamReader(is));
    
                logList = br.lines()
                                .skip(1)
                                .map(mapToLog)
                                .collect(Collectors.toList());
    
    
    
    
                logList.stream().forEach(System.out::println);
    
                groupByLogId = logList.stream()
                                .collect(Collectors.groupingBy(Log::getLog_Id));
    
    
                for (Entry<String, List<Log>> entryForLog : groupByLogId.entrySet()) {
                    System.out.println(" Entity Id " + entryForLog.getKey()
                            + "        |        Value : " + entryForLog.getValue());
                }
    
    
    
    
    
    
                br.close();
                return groupByLogId;
    
    
    
        }
    
    
    
        public String getLog_Id() {
            return log_Id;
        }
    
    
    
        public void setLog_Id(String log_Id) {
            this.log_Id = log_Id;
        }
    
    
    
        public String getStartTime() {
            return startTime;
        }
    
    
    
        public void setStartTime(String startTime) {
            this.startTime = startTime;
        }
    
    
    
        public String getEndTime() {
            return endTime;
        }
    
    
    
        public void setEndTime(String endTime) {
            this.endTime = endTime;
        }
    
    
    
        public static List<Log> getLoglist() {
            return logList;
        }
    
    
    
        public Log(String log_Id, String startTime, String endTime) {
            super();
            this.log_Id = log_Id;
            this.startTime = startTime;
            this.endTime = endTime;
        }
    
    
    
        @Override
        public String toString() {
    
            return (new StringBuffer()
                        .append(log_Id).append(",")
                        .append(startTime).append(",")
                        .append(endTime)
                        ).toString();
    
        }
    
    
    }
    
    公共类日志{
    私有静态最终字符串inputFileName=“D:\\path\\to\\Log.csv”;
    私有静态最终字符串outputFileName=“D:\\path\\to\\Output\\Log.csv”;
    私有静态列表logList=null;
    私有静态映射groupByLogId=newhashmap();
    私有字符串日志Id;
    私有字符串开始时间;
    私有字符串结束时间;
    公共静态映射createLogMap()引发IOException{
    函数mapToLog=(行)->{
    字符串[]p=line.split(“,(?=(?:[^\“]*\”[^\“]*\”[^\“]*\”*[^\“]*$)”,-1);
    Log Log=新日志(p[0],p[1],
    p[2]);
    返回日志;
    };
    InputStream=null;
    BufferedReader br=null;
    is=新文件InputStream(新文件(inputFileName));
    br=新的BufferedReader(新的InputStreamReader(is));
    logList=br.lines()
    .skip(1)
    .map(mapToLog)
    .collect(Collectors.toList());
    logList.stream().forEach(System.out::println);
    groupByLogId=logList.stream()
    .collect(Collectors.groupingBy(Log::getLog_Id));
    for(条目entryForLog:groupByLogId.entrySet()){
    System.out.println(“实体Id”+entryForLog.getKey()
    +|值:“+entryForLog.getValue());
    }
    br.close();
    返回groupByLogId;
    }
    公共字符串getLog_Id(){
    返回日志Id;
    }
    公共无效设置日志Id(字符串日志Id){
    this.log\u Id=log\u Id;
    }
    公共字符串getStartTime(){
    返回起始时间;
    }
    公共无效设置开始时间(字符串开始时间){
    this.startTime=startTime;
    }
    公共字符串getEndTime(){
    返回结束时间;
    }
    公共void setEndTime(字符串endTime){
    this.endTime=endTime;
    }
    公共静态列表getLoglist(){
    返回日志列表;
    }
    公共日志(字符串日志Id、字符串开始时间、字符串结束时间){
    超级();
    this.log\u Id=log\u Id;
    this.startTime=startTime;
    this.endTime=endTime;
    }
    @凌驾
    公共字符串toString(){
    返回(新的StringBuffer()
    .append(log_Id).append(“,”)
    .append(开始时间)。append(“,”)
    .append(结束时间)
    ).toString();
    }
    }
    
    非常感谢您的帮助

    预期产出:


    LogId:LogId,min(StartTime),max(EndTime)
    当然,将时间存储为字符串不是一个好主意。最好使用
    LocalDateTime
    之类的内容。在这个答案中,我假设字符串时间戳表示是可比较的,所以我可以使用
    date1.compareTo(date2)

    另外,我强烈建议您删除使
    Log
    对象不可变的setter。它们不会增加任何值,只会在偶尔更改现有对象时使程序更难调试

    回到您的问题,添加如下合并方法:

    class Log {
        ...
        Log merge(Log other) {
            if(!other.getLog_Id().equals(this.getLog_Id())) {
                throw new IllegalStateException();
            }
            String start = this.getStartTime().compareTo(other.getStartTime()) < 0 ?
                           this.getStartTime() : other.getStartTime();
            String end = this.getEndTime().compareTo(other.getEndTime()) > 0 ?
                         this.getEndTime() : other.getEndTime();
            return new Log(this.getLog_Id, start, end);
        }
    }
    

    这样,当出现两个具有相同
    log\u Id
    的日志条目时,将为它们调用
    merge
    方法来创建合并的日志条目。

    “如何使用java 8中的stream以最小的代码和最大的效率实现这一点?”。“-我觉得它太宽泛了,请尝试更具体地回答您的问题。在
    之前,尝试使用
    map
    int/long
    ,该代码看起来很古老。您应该使用
    StringBuilder
    而不是
    StringBuffer
    ,但实际上,简单地使用
    log\u Id+“,+startTime+”,“+endTime
    会自动为您带来好处。与简单表达式相比,更复杂的
    toString()
    实现没有任何好处。此外,您应该使用
    try(…){…}
    语句来管理资源。无需手动调用
    close()
    ,您在异常情况下无法正确关闭的问题就消失了。此外,您不再需要重复类型参数:
    groupByLogId=newhashmap()
    将从变量推断类型。
    streamOfLogs.collect(
        Collectors.toMap(Log::getLog_Id, Function.identity(), Log::merge));