使用Java8是否可以一步创建一个列表或任何其他数据结构(分组、排序和计数)?

使用Java8是否可以一步创建一个列表或任何其他数据结构(分组、排序和计数)?,java,java-8,Java,Java 8,我有一个具有此结构的文件: a, City1, 2013-09-05 14:08:15 b, City2, 2015-10-08 16:10:15 c, City2, 2010-09-05 14:08:15 d, City1, 2011-09-05 14:08:15 a、 2013-09-05 14:08:15第1城市 b、 城市2,2015-10-08 16:10:15 c、 城市2,2010-09-05 14:08:15 d、 2011-09-05 14:08:15城市1 它是以逗号分隔的值

我有一个具有此结构的文件:

a, City1, 2013-09-05 14:08:15 b, City2, 2015-10-08 16:10:15 c, City2, 2010-09-05 14:08:15 d, City1, 2011-09-05 14:08:15 a、 2013-09-05 14:08:15第1城市 b、 城市2,2015-10-08 16:10:15 c、 城市2,2010-09-05 14:08:15 d、 2011-09-05 14:08:15城市1 它是以逗号分隔的值和以行尾字符分隔的行

我需要在Java8中创建一个数据结构,在该结构中,我按城市对行进行分组,并在每个这样的组中按日期升序排序,并计算每个组中的行数

我试过:

  • 从文件创建
    列表
  • 创建一张
    地图
    ,该地图按城市分组,并按日期对每组进行排序
  • 创建一个
    地图
    ,用于按城市和行数分组
  • 这是我尝试过的代码:

    public PhotoResponse processFile()  {
        //read each line of the file and create a new object PhotoIn for each one
        List<PhotoIn> lista = null;
        try {
            lista = Files.lines(Paths.get(file))
            .map(line -> line.split(","))
            .map(photo -> new PhotoIn(photo[0].substring(0, photo[0].lastIndexOf(".")), photo[0].substring(photo[0].lastIndexOf(".") + 1 ), photo[1].trim(), parseDate(photo[2]), index++))
            .collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return generateOutput(lista); 
    }
    
    
    private PhotoResponse generateOutput(List<PhotoIn> photos) {
    
        //Grouping photos by city
        Map<String, List<PhotoIn>> photosByCity = photos.stream().collect(Collectors.groupingBy(PhotoIn::getCity));
    
        //Sorting photos by date into each city
        photosByCity.values().forEach(list -> list.sort(Comparator.comparing(PhotoIn::getDate)));
    
        //Grouping photos by city and amount
        Map<String, Long> numeroPorCiudades = photos.stream().collect(Collectors.groupingBy(PhotoIn::getCity, Collectors.counting()));
    
        List<PhotoOut> photoOutList = new ArrayList<PhotoOut>();
    
        photosByCity.forEach((key, list) -> {
            String digits = Integer.toString(Long.toString(numeroPorCiudades.get(key)).length());
            counter = 1;
            list.forEach(photoIn -> {
                photoOutList.add(new PhotoOut(photoIn.getName() + "." + photoIn.getExtension(), key + String.format("%0" + digits + "d", counter++) + "." + photoIn.getExtension(), photoIn.getIndex()));
            });
        });
        return sortOutput(photoOutList);
    }
    
    公共光响应处理文件(){
    //读取文件的每一行,并为每一行创建一个新对象PhotoIn
    List lista=null;
    试一试{
    lista=Files.lines(path.get(file))
    .map(直线->直线分割(“,”)
    .map(photo->new PhotoIn(photo[0]。子字符串(0,photo[0]。lastIndexOf(“.”),photo[0]。子字符串(photo[0]。lastIndexOf(“.”+1),photo[1]。trim(),parseDate(photo[2]),index++)
    .collect(Collectors.toList());
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    返回生成输出(lista);
    }
    专用光响应生成输出(列表照片){
    //按城市分组照片
    Map photosByCity=photos.stream().collect(Collectors.groupingBy(PhotoIn::getCity));
    //按日期将照片分类到每个城市
    forEach(list->list.sort(Comparator.comparing(PhotoIn::getDate));
    //按城市和数量分组照片
    Map numeroPorCiudades=photos.stream().collect(Collectors.groupingBy(PhotoIn::getCity,Collectors.counting());
    List photoOutList=new ArrayList();
    photosByCity.forEach((键,列表)->{
    字符串位数=Integer.toString(Long.toString(numerioporciudades.get(key)).length());
    计数器=1;
    列表。forEach(照片输入->{
    photoOutList.add(新的PhotoOut(photoIn.getName()+“+photoIn.getExtension(),键+字符串.格式(“%0”+数字+“d”,计数器++)+“+photoIn.getExtension(),photoIn.getIndex()));
    });
    });
    返回排序输出(photoOutList);
    }
    
    我正在解决这个问题,但我正在寻找一种更好、更有效的方法来使用Java8是否可以在一个步骤中完成这三个步骤?。我需要的是将所有信息分组到一个数据结构中。

    使用该模型:

    class Model {
      private String title;
      private String city;
      private LocalDateTime date;
    }
    
    可以这样做:

    List<Model> list = getFromFile();
    
    Comparator<Model> comparator = Comparator.comparing(Model::getDate);
    
    //grouping the list by City with lists sorted by date
    Map<String, List<Model>> map = list.stream()
        .collect(
            Collectors.groupingBy( //grouping the list by City with lists 
                m -> m.getCity(),
                Collectors.collectingAndThen(Collectors.toList(), l->{
                  l.sort(comparator);
                  return l;
                })
            )
        );
    
    //getting another map with counts
    Map<String, Object> countMap = map.entrySet().stream()
        .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().size()));
    
    List List=getFromFile();
    Comparator Comparator=Comparator.comparing(Model::getDate);
    //使用按日期排序的列表按城市对列表进行分组
    Map=list.stream()
    .收集(
    Collectors.groupingBy(//使用列表按城市对列表进行分组
    m->m.getCity(),
    Collectors.collectionAndThen(Collectors.toList(),l->{
    l、 排序(比较器);
    返回l;
    })
    )
    );
    //获取另一张带有计数的地图
    Map countMap=Map.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey,Entry->Entry.getValue().size());
    
    对于该型号:

    class Model {
      private String title;
      private String city;
      private LocalDateTime date;
    }
    
    可以这样做:

    List<Model> list = getFromFile();
    
    Comparator<Model> comparator = Comparator.comparing(Model::getDate);
    
    //grouping the list by City with lists sorted by date
    Map<String, List<Model>> map = list.stream()
        .collect(
            Collectors.groupingBy( //grouping the list by City with lists 
                m -> m.getCity(),
                Collectors.collectingAndThen(Collectors.toList(), l->{
                  l.sort(comparator);
                  return l;
                })
            )
        );
    
    //getting another map with counts
    Map<String, Object> countMap = map.entrySet().stream()
        .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().size()));
    
    List List=getFromFile();
    Comparator Comparator=Comparator.comparing(Model::getDate);
    //使用按日期排序的列表按城市对列表进行分组
    Map=list.stream()
    .收集(
    Collectors.groupingBy(//使用列表按城市对列表进行分组
    m->m.getCity(),
    Collectors.collectionAndThen(Collectors.toList(),l->{
    l、 排序(比较器);
    返回l;
    })
    )
    );
    //获取另一张带有计数的地图
    Map countMap=Map.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey,Entry->Entry.getValue().size());
    
    分享您的解决方案。到目前为止,您得到了什么?解决方案大概将由I/O主导。聪明的人可能更容易理解。选择单行程序,可能是
    收集器。使用
    TreeSet
    收集器按
    收集器分组。行数只是在
    集合
    上调用
    大小
    。请不要删除您发布的代码,因为这样做可能会使现有答案无效。顺便说一下,您的城市和日期字符串前面会有一个空格。在
    (逗号+空格)上拆分,而不是
    。或者事后再打电话。@BasilBourque谢谢。这只是目前代码的预览。我已经做了一些更正。请分享您的解决方案。到目前为止,您得到了什么?解决方案大概将由I/O主导。聪明的人可能更容易理解。选择单行程序,可能是
    收集器。使用
    TreeSet
    收集器按
    收集器分组。行数只是在
    集合
    上调用
    大小
    。请不要删除您发布的代码,因为这样做可能会使现有答案无效。顺便说一下,您的城市和日期字符串前面会有一个空格。在
    (逗号+空格)上拆分,而不是
    。或者事后再打电话。@BasilBourque谢谢。这只是目前代码的预览。我已经做了一些修正。@icj03刚刚测试过,一切对我来说都很好,我甚至没有任何来自Intellij想法的警告。我不知道,可能是某个jvm特定的问题。我使用的是1.8.0Ó我实际上讨厌旧的API,但这不是问题所在。编辑了LocalDateTime的答案,它根本没有影响算法。如果先排序,然后分组,而不使用
    Collectors::collecting,则会得到完全相同的结果,然后
    @icj03刚刚对其进行了测试,对我来说一切正常,我的Intellij想法甚至没有任何警告。我不知道,可能是某个jvm特定的问题。我使用的是1.8.0Ó我实际上讨厌旧的API,但它不是