gpt4 book ai didi

java - 计算对象 map 中的平均倍数

转载 作者:行者123 更新时间:2023-11-30 08:20:33 24 4
gpt4 key购买 nike

我有格式的 map

Map<String, List<TableDTO>>

public class TableDTO {
private String countryName;
private String sourceName;
private int year;
private Double usageValue;
private Double powerUsers;

//Setter & Getters

}

我想找到 usageValues 和 powerUsers 的平均值,并且仍然保持 TableDTO 结构并且 usageValue 可以为 null,如果它为 null,则完全忽略该对象。

<Chrome, <UK, Lorem, 2013, 2.90, 5.4>>
<Chrome, <US, Lorem, 2013, 4.10, 1.5>>
<Chrome, <EU, Lorem, 2013, 1.20, 0.22>>
<Chrome, <Asia, Lorem, 2013, 3.90, -1.10>>

<IE, <UK, Lorem, 2013, 1.40, 24.4>>
<IE, <US, Lorem, 2013, 0.90, 14.4>>
<IE, <EU, Lorem, 2013, 2.10, 0>>
<IE, <Asia, Lorem, 2013, 0.90, 0.4>>

<FF, <UK, Lorem, 2013, 0.10, 2.14>>
<FF, <US, Lorem, 2013, 1.10, 4.0>>
<FF, <EU, Lorem, 2013, , 4.4>>
<FF, <Asia, Lorem, 2013, 2.90, 4.4>>

预期结果

<1, <UK, Lorem, 2013, 1.47, 10.65>>
<2, <US, Lorem, 2013, 2.03, 6.63>>
<3, <Asia, Lorem, 2013, 2.57, 1.23>>

现在在结果中我已经用索引替换了键,现在没问题。您会注意到,由于 EU 的 FF 具有空值,因此整个 EU 已被忽略,但对于其余部分,我计算了平均值。

这如何在 Java 8 中使用 Lambda 表达式来完成,还是我必须迭代?

更新 1:这是我目前得到的:

1. 
Map<String, List<TableDTO>> dump = mapOfAllData.values()
.stream()
.flatMap(list -> list.stream())
.collect(Collectors.groupingBy(TableDTO::getCountryName));

Which give me a map with country names and the DTO orderd

2.
dump.values().stream().flatMap(list -> list.stream())
.filter((o -> !o.getUsageValue().isEmpty()))
.collect(Collectors.mapping(TableDTO::getUsageValue, Collectors.averagingDouble(Double::parseDouble)));

基本上取平均值,但不删除usageValue为空的DTO,我目前正在尝试解决。

更新 2:

我成功地从我的 map 中删除了不需要的国家。

我想弄清楚如何找到两个元素的平均值,我有这个表达式

 newMap.values().stream().flatMap(list -> list.stream())
.collect(Collectors.mapping(TableDTO::usageValue, Collectors.averagingDouble(s -> s.isEmpty() ? Double.NaN : Double.parseDouble(s))));
// Collectors.mapping(TableDTO::powerUsers, Collectors.averagingDouble(c -> c.isEmpty() ? Double.NaN : Double.parseDouble(c))));

但我无法获得 powerUsers 的平均值。

最佳答案

为了理解,您需要每个 List<TableDTO> 的平均值用groupBy countryName , sourceName , year但平均值在不同的领域?

我会期待 usagePowerpowerUsers成为Double ,而不是像您的代码和您对 Double.parseDouble 的使用那样的 String建议。

这段代码应该做到这一点:

package stackoverflow;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

public class TableDTO {
private final String countryName;
private final String sourceName;
private final int year;
@Nullable
private final Double usageValue;
private final Double powerUsers;

public TableDTO(final String countryName, final String sourceName, final int year, final Double usageValue,
final Double powerUsers) {
this.countryName = countryName;
this.sourceName = sourceName;
this.year = year;
this.usageValue = usageValue;
this.powerUsers = powerUsers;
}

public String getCountryName() {return countryName;}
public String getSourceName() {return sourceName;}
public int getYear() {return year;}
@Nullable public Double getUsageValue() {return usageValue;}
public Double getPowerUsers() {return powerUsers;}

@Override
public String toString() {
return "TableDTO [countryName=" + countryName + ", sourceName=" + sourceName + ", year=" + year + ", usageValue="
+ usageValue + ", powerUsers=" + powerUsers + "]";
}

public static void main(final String[] args) {

final java.util.Map<String, java.util.List<TableDTO>> data = new LinkedHashMap<>();

final List<TableDTO> chrome = new ArrayList<>();
chrome.add(new TableDTO("UK", "Lorem", 2013, 2.90, 5.4));
chrome.add(new TableDTO("US", "Lorem", 2013, 4.10, 1.5));
chrome.add(new TableDTO("EU", "Lorem", 2013, 1.20, 0.22));
chrome.add(new TableDTO("Asia", "Lorem", 2013, 3.90, -1.10));
data.put("Chrome", chrome);

final List<TableDTO> ie = new ArrayList<>();
ie.add(new TableDTO("UK", "Lorem", 2013, 1.40, 24.4));
ie.add(new TableDTO("US", "Lorem", 2013, 0.90, 14.4));
ie.add(new TableDTO("EU", "Lorem", 2013, 2.10, 0.));
ie.add(new TableDTO("Asia", "Lorem", 2013, 0.90, 0.4));
data.put("IE", ie);

final List<TableDTO> fx = new ArrayList<>();
fx.add(new TableDTO("UK", "Lorem", 2013, 0.10, 2.14));
fx.add(new TableDTO("US", "Lorem", 2013, 1.10, 4.0));
fx.add(new TableDTO("EU", "Lorem", 2013, null, 4.4));
fx.add(new TableDTO("Asia", "Lorem", 2013, 2.90, 4.4));
data.put("FX", fx);

data.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(dto -> Arrays.asList(dto.getCountryName(), dto.getSourceName(), dto.getYear())))
.values()
.stream()
.filter(list -> list.stream().map(TableDTO::getUsageValue).noneMatch(Objects::isNull))
.map(
values -> {
final TableDTO root = values.iterator().next();

final double usageValueAvg = values.stream().map(TableDTO::getUsageValue).filter(Objects::nonNull)
.collect(Collectors.averagingDouble(Double::doubleValue));
final double powerUsersAvg = values.stream().map(TableDTO::getPowerUsers)
.collect(Collectors.averagingDouble(Double::doubleValue));

return new TableDTO(root.getCountryName(), root.getSourceName(), root.getYear(), usageValueAvg,
powerUsersAvg);

}).forEach(System.out::println);
;

}
}

结果是:

TableDTO [countryName=UK, sourceName=Lorem, year=2013, usageValue=1.4666666666666666, powerUsers=10.646666666666667]
TableDTO [countryName=US, sourceName=Lorem, year=2013, usageValue=2.033333333333333, powerUsers=6.633333333333333]
TableDTO [countryName=Asia, sourceName=Lorem, year=2013, usageValue=2.5666666666666664, powerUsers=1.2333333333333334]

以及解释:我已经使用了您的一些代码来完成它。

  • 做一个flatMapdata 的值之上:

    data.values()
    .stream()
    .flatMap(List::stream)
  • 将您的 TableDTO 分组通过一些键:我们不关心键,唯一重要的是它正确地实现了 hashCodeequals . Arrays.asList完成工作。否则,创建一个 Tuple 类,它接受一个数组并使用 Arrays.hashCode/equals .

        .collect(Collectors.groupingBy(dto -> Arrays.asList(dto.getCountryName(), dto.getSourceName(), dto.getYear())))
    .values()
    .stream()

    因为我们不需要列表,所以我们选择值并使用流。

  • 我们筛选 TableDTO其中包含一个空的 usageValue :

        .filter(list -> list.stream().map(TableDTO::getUsageValue).noneMatch(Objects::isNull))
  • 然后我们绘制一张 map ,在您未能找到解决方案的地方:因为小组,所有 TableDTO同享countryName , sourceNameyear值(value)。但不是 usageValuepowerUsers .

    因为列表不能为空,所以我们得到第一个元素。

        .map(
    values -> {
    final TableDTO root = values.iterator().next();
  • 在另一个结果中,我们计算过滤掉 usageValue 的任何空值的两个平均值.

              final double usageValueAvg = values.stream().map(TableDTO::getUsageValue).filter(Objects::nonNull)
    .collect(Collectors.averagingDouble(Double::doubleValue));
    final double powerUsersAvg = values.stream().map(TableDTO::getPowerUsers)
    .collect(Collectors.averagingDouble(Double::doubleValue));
  • 然后我们返回一个新的TableDTO基于三个分组键和两个平均值。

              return new TableDTO(root.getCountryName(), root.getSourceName(), root.getYear(), usageValueAvg,
    powerUsersAvg);

    })
  • 然后我们打印它,瞧! :)

          .forEach(System.out::println);

希望它能解决您的问题。

我在 Eclipse 中对其进行了测试,它可以编译,但是使用 javac 可能会失败,因为编译器与 Lambdas 的工作方式不同。

关于java - 计算对象 map 中的平均倍数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25974488/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com