问题描述
我有一种方法将 .txt 文件读入二维数组,该 txt 文件包含带有“Y”或“N”的行以及 1-24 的团队编号(行看起来像“T# Y”或“ T# N”,然后我在该二维数组中搜索行中的特定元素(“Y”)并返回有多少行带有“Y”并为每个团队计算真实案例的数量。
24 个团队,至少我认为在二维数组中应该是 24 行!
public static String[][] buildTimes(String[][] sub) {
StringBuilder scores = new StringBuilder(sub.length);
for (String[] row : sub) {
scores.append(Arrays.stream(row)
.filter(str -> str.equalsIgnoreCase("Y"))
.toArray().length);
scores.append("/");
}
String[] tempArray = scores.toString().split("");
String[][] finalTimes = new String[24][1];
for (int i = 0; i < finalTimes.length; i++) {
for (int j = 0; j < finalTimes[i].length; j++) {
int index = 0;
finalTimes[i][j] = tempArray[index];
index++;
}
}
return finalTimes;
}
我收到错误:
Exception in thread "main" java.lang.NullPointerException
at test.lambda$buildTimes$0(test.java:74)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at java.base/java.util.stream.AbstractPipeline.evaluatetoArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:523)
at test.buildTimes(test.java:74)
at run.main(run.java:10)
我不知道为什么会出现这些错误,我绝对没有使用 StringBuilders 的经验,我也尝试过使用 INT ArrayList 和相同的错误。
输出示例: 团队 1(为团队 1 找到的 Y 计数) 团队 2(“”代表团队 2) 第 3 队(“”代表第 3 队)
我只需要一个二维数组,其中包含第 1 列到第 24 列文件的行中每个团队的团队# 和“Y”。
解决方法
只要问题中已经使用了 Stream API,最好使用其工具来计算使用 Collectors::groupingBy
而不是 StringBuilder
的元素的频率。如果将频率计算为 Integer
很重要,则可以使用 Collectors::summingInt
而不是 Collectors::counting
返回 Long
。
可以使用 IntStream::range
或 IntStream::rangeClosed
实现可以如下:
public static String[][] countYesPerTeam(String[][] data) {
Map<String,Integer> map = Arrays.stream(data)
.filter(item -> item.length > 1 && "Y".equalsIgnoreCase(item[1]))
.collect(Collectors.groupingBy(item -> item[0],Collectors.summingInt(item -> 1)));
return IntStream.rangeClosed(1,24)
.mapToObj(i -> new String[] {
"T" + i,Integer.toString(map.getOrDefault("T" + i,0))
}) // provide [TN,yesCount] per team
.toArray(String[][]::new);
}
测试
String[][] data = {{"T1","Y"},{"T2",{"T1","N"},{"T4","y"}};
String[][] stat = countYesPerTeam(data);
System.out.println(Arrays.deepToString(stat));
输出:
[[T1,1],[T2,2],[T3,0],[T4,[T5,[T6,[T7,[T8,[T9,[T10,[T11,[T12,[T13,[T14,[T15,[T16,[T17,[T18,[T19,[T20,[T21,[T22,[T23,[T24,0]]
如果结果数组中不需要团队名称,则可以将其创建为:
// ....
return IntStream.rangeClosed(1,24)
.mapToObj(i -> new String[] {
Integer.toString(map.getOrDefault("T" + i,0))
}) // provide [yesCount] per team
.toArray(String[][]::new);
,
您可以通过简单的方式解决问题:
public static void main(String[] args) {
String[][] a = {{"T1","Y"}};
System.out.println(buildTimes(a)); // {T1=2,T2=1}
}
public static Map<String,Long> buildTimes(String[][] data){
return Stream.of(data)
.filter(item -> item.length > 1)
.filter(item -> "y".equalsIgnoreCase(item[1]))
.map(item -> item[0])
.collect(groupingBy(item -> item,Collectors.counting()));
}