gpt4 book ai didi

Java HashMap /数组列表计数不同值

转载 作者:行者123 更新时间:2023-11-30 06:21:32 25 4
gpt4 key购买 nike

我对编程还很陌生,我有一个作业要做,但我陷入了困境。

我必须实现一个程序,该程序将读取 CSV 文件(超过 100 万行)并计算在特定日期有多少客户订购了“x”个不同的产品。

CSV 如下所示:

Product Name | Product ID | Client ID |  Date
Name 544 86 10/12/2017
Name 545 86 10/12/2017
Name 644 87 10/12/2017
Name 644 87 10/12/2017
Name 9857 801 10/12/2017
Name 3022 801 10/12/2017
Name 3021 801 10/12/2017

我的代码的结果是:

801: 2 - incorrect

86: 2 - correct

87: 2 - incorrect

期望的输出是:

Client 1 (801): 3 distinct products

Client 2 (86): 2 distinct products

Client 3 (87): 1 distinct product

此外,

  • 如果我想知道有多少客户订购了 2 种不同的产品,我希望结果如下所示:

总计:1 位客户订购了 2 种不同的产品

  • 如果我想知道一天内订购的不同产品的最大数量,我希望结果如下所示:

订购的不同产品的最大数量为:3

我尝试使用 Google Guava 的 Hash Map 和 Multimap(我的最佳猜测),但我无法理解它。

我的代码如下所示:

package Test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;

public class Test {

public static void main(String[] args) {
//HashMultimap<String, String> myMultimap = HashMultimap.create();
Map<String, MutableInteger> map = new HashMap<String, MutableInteger>();
ArrayList<String> linesList = new ArrayList<>();
// Input of file which needs to be parsed
String csvFile = "file.csv";
BufferedReader csvReader;

// Data split by 'TAB' in CSV file
String csvSplitBy = "\t";
try {
// Read the CSV file into an ArrayList array for easy processing.
String line;
csvReader = new BufferedReader(new FileReader(csvFile));
while ((line = csvReader.readLine()) !=null) {
linesList.add(line);
}
csvReader.close();
} catch (IOException e) {
e.printStackTrace();
}

// Process each CSV file line which is now contained within
// the linesList list Array
for (int i = 0; i < linesList.size(); i++) {
String[] data = linesList.get(i).split(csvSplitBy);
String col2 = data[1];
String col3 = data[2];
String col4 = data[3];

// Determine if Column 4 has the desired date
// and count the values
if (col4.contains("10/12/2017")) {
String key = col3;
if (map.containsKey(key)) {
MutableInteger count = map.get(key);
count.set(count.get() + 1);
} else {
map.put(key, new MutableInteger(1));
}
}
}

for (final String k : map.keySet()) {
if (map.get(k).get() == 2) {
System.out.println(k + ": " + map.get(k).get());
}
}
}
}

任何有关如何实现的意见或建议将不胜感激。

提前谢谢你们。

最佳答案

您可以为每个 clientId 存储一组productIds,并仅获取其大小。由于Set不允许重复值,这将有效地为您提供不同数量的productIds

此外,我建议您为变量指定有意义的名称,而不是 col2、k、map...这将使您的代码更具可读性。

Map<String, Set<String>> distinctProductsPerClient = new HashMap<String, Set<String>>();
// Process each CSV file line which is now contained within
// the linesList list Array
// Start from 1 to skip the first line
for (int i = 1; i < linesList.size(); i++) {
String line = linesList.get(i);
String[] data = line.split(csvSplitBy);
String productId = data[1];
String clientId = data[2];
String date = data[3];

// Determine if Column 4 has the desired date
// and count the values
if (date.contains("10/12/2017")) {
if (!distinctProductsPerClient.containsKey(clientId)) {
distinctProductsPerClient.put(clientId, new HashSet<>());
}
distinctProductsPerClient.get(clientId).add(productId);

}
}

for (final String clientId : distinctProductsPerClient.keySet()) {
System.out.println(clientId + ": " + distinctProductsPerClient.get(clientId).size());
}

使用 Stream API 的更高级解决方案(需要 Java 9)

如果您引入类 OrderData(代表 CSV 中的单行),如下所示:

private static class OrderData {

private final String productName;
private final String productId;
private final String clientId;
private final String date;

public OrderData(String csvLine) {

String[] data = csvLine.split("\t");

this.productName = data[0];
this.productId = data[1];
this.clientId = data[2];
this.date = data[3];

}

public String getProductName() {
return productName;
}

public String getProductId() {
return productId;
}

public String getClientId() {
return clientId;
}

public String getDate() {
return date;
}
}

您可以用以下内容替换 for 循环:

Map<String, Set<String>> distinctProductsPerClient2 = linesList.stream()
.skip(1)
.map(OrderData::new)
.collect(groupingBy(OrderData::getClientId, mapping(OrderData::getProductId, toSet())));

但我认为,如果您是编程新手,这可能有点复杂(尽管如果您尝试了解上述代码的作用,这可能是一个很好的练习)。

关于Java HashMap /数组列表计数不同值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48042112/

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