java - Stringbuilder 到 Array 到 2D Array 导致 NullPointerException JAVA
问题描述
我有一种将 .txt 文件读入二维数组的方法,该 txt 文件包含带有“Y”或“N”的行以及 1-24 的团队编号(行看起来像“T# Y”或“T#N “,然后我在该二维数组中搜索行中的特定元素(“Y”),并返回有多少行有“Y”,并为每个团队计算真实案例的数量。
24 个团队,我认为至少应该是 2d 数组中的 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 的“”)
我只需要一个包含 Team# 的 2D 数组,并且在第 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", "Y"}, {"T1", "N"}, {"T2", "Y"}, {"T4", "y"}};
String[][] stat = countYesPerTeam(data);
System.out.println(Arrays.deepToString(stat));
输出:
[[T1, 1], [T2, 2], [T3, 0], [T4, 1], [T5, 0], [T6, 0], [T7, 0], [T8, 0], [T9, 0], [T10, 0], [T11, 0], [T12, 0], [T13, 0], [T14, 0], [T15, 0], [T16, 0], [T17, 0], [T18, 0], [T19, 0], [T20, 0], [T21, 0], [T22, 0], [T23, 0], [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);
推荐阅读
- r - 在 ggplot facet 中添加一个表
- javascript - 不确定如何将对象内容映射到应用程序中显示
- python - AttributeError:在库中找不到函数/符号“ARC4_stream_init”(Python)
- regex - 正则表达式在管道字符上拆分,除非在方括号中
- php - 从 PHP 类中的函数获取值
- excel - Excel VBA:将范围,单个单元格复制到另一个工作簿
- python - 反向地理编码 - 使用 geopy.Nominatim 获取邮政编码
- sqlite - 在 SQLite 中检查正确的电子邮件格式
- python-3.x - 追加和处理重复项
- c# - Jquery/Ajax 更新表[ASP.NET Core MVC]