如何在Java 8中使用lambda表达式的多个流和.map函数

6

我有一个List counties,其中只包含唯一的县名,还有一个List txcArray,其中包含城市名称、县名和该城市的人口。

我需要使用Java 8的lambda表达式和Stream,从txcArray中获取每个县的最大城市名称。

这是我目前的代码:

List<String> largest_city_name = 
    counties.stream() 
            .map(a -> txcArray.stream()
                              .filter(b ->  b.getCounty().equals(a))
                              .mapToInt(c -> c.getPopulation())
                              .max())
            .collect( Collectors.toList());

我正在尝试在.max()之后添加另一个.map语句,以获取人口最多的City的名称,但我的新lambda表达式并不存在于txcArray流中,它只将其识别为int类型和texasCitiesClass类型。这是我想做的。

 List<String> largest_city_name = 
     counties.stream() 
             .map(a -> txcArray.stream()
                               .filter( b ->  b.getCounty().equals(a))
                               .mapToInt(c->c.getPopulation())
                               .max()
                               .map(d->d.getName()))
             .collect( Collectors.toList());

有人能告诉我我做错了什么吗?

2个回答

5
你不需要完整的 counties 列表。只需要流式处理 txcArray 并按照县进行分组:
Collection<String> largestCityNames = txcArray.stream()
        .collect(Collectors.groupingBy(
                City::getCounty,
                Collectors.collectingAndThen(
                        Collectors.maxBy(City::getPopulation),
                        o -> o.get().getName())))
        .values();

不错。我没想到那个。简单多了。+1 - Eran
我想,最初的意图是最大城市名称列表与县列表的顺序相同。在这里,保留Map而不是无序的城市名称集合可能更好... - Holger

3

将城市的Stream映射为IntStream后,您就无法恢复与int值相对应的城市名称。

使用Streammax而不是转换为IntStream

List<String> largest_city_name =
    counties.stream() 
            .map(a -> txcArray.stream()
                              .filter(b ->  b.getCounty().equals(a))
                              .max(Comparator.comparingInt(City::getPopulation))
                              .get())
            .map(City::getName)
            .collect(Collectors.toList());

这样,map操作将每个县映射到其人口最多的City。请注意,max返回一个Optional<City>,因此如果Optional为空(即某些县没有城市),get()将抛出异常。

为了避免这个问题,您可以这样写:

List<String> largest_city_name =
    counties.stream() 
            .map(a -> txcArray.stream()
                              .filter(b ->  b.getCounty().equals(a))
                              .max(Comparator.comparingInt(City::getPopulation))
                              .map(City::getName)
                              .orElse(""))
            .collect(Collectors.toList());

这将把没有城市的县映射为空的 String

此代码假定 txcArray 是一个 List<City>,其中 City 是:

class City { public String getName () {return nam;} public int getPopulation() {return pop;} public String getCounty() {return cnt;} String nam; int pop; String cnt; public City(String nam,int pop,String cnt) { this.nam = nam; this.pop = pop; this.cnt = cnt; } }

counties 则是一个 List<String>。如果我的假设不准确,则需要进行一些调整。

现在,使用以下 Lists 对代码进行测试:

List<String> counties=new ArrayList<> ();
counties.add ("First");
counties.add ("Second");
counties.add ("Third");
counties.add ("Fourth");
List<City> txcArray = new ArrayList<> ();
txcArray.add (new City("One",15000,"First"));
txcArray.add (new City("Two",12000,"First"));
txcArray.add (new City("Three",150000,"Second"));
txcArray.add (new City("Four",14000,"Second"));
txcArray.add (new City("Five",615000,"Third"));
txcArray.add (new City("Six",25000,"Third"));

以下是 List 输出的结果:

[One, Three, Five, ]

你说得对,我用了错误的变量名。谢谢你帮我解决了这个问题。 - Octavio garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接