我有一个团队的HashMap,我需要打印出来。它们需要被索引并按一些参数排序(不相关)。一切正常,除了索引部分,我在某种程度上工作,但感觉不对。
int i=0;
public void printTable()
{
StringBuilder sb = new StringBuilder();
i = 0;
table.keySet().stream()
.map(key -> table.get(key))
.sorted(Comparator.comparing(Team::getPoints).thenComparing(Team::goalDifference).reversed().thenComparing(Team::getName))
.forEach(team -> sb.append(String.format("%2d%s %-15s%5d%5d%5d%5d%5d\n", ++i, ".", team.getName(), team.getPlayed(),
team.getWins(), team.getDraws(), team.getLosses(), team.getPoints())));
System.out.print(sb.toString());
}
有更好的方法吗?我不认为Intstream会在这里提供帮助,因为我无法使用索引从HashMap中获取对象。
答案 0 :(得分:2)
您应该避免使用有状态的流/ lambda表达式。 reference。由于这个原因,我在下面的原始答案是一个坏主意。
更好的方法是将流和打印分开。
List<Team> teams = table.values()
.stream()
.sorted(...)
.collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for(int i=0; i<teams.size(); i++) {
Team team = teams.get(i);
sb.append(String.format("%2d. %-15s%5d%5d%5d%5d%5d\n",
i,
team.getName(),
team.getPlayed(),
team.getWins(),
team.getDraws(),
team.getLosses(),
team.getPoints()));
}
System.out.println(sb.toString());
您无法修改在流或lambda中使用的变量/修改基元的引用。您可以像下面那样重写代码,
AtomicInteger i = new AtomicInteger();
String result = table.values()
.stream()
.sorted(...)
.map(e -> i.incrementAndGet() + "_" + e)
.collect(Collectors.joining());
AtomicInteger
会在不更改引用/修改基元的情况下为您提供可变性。您不需要在地图中查找,您可以直接迭代值。
修改
正如@Eugene在评论中指出的那样,如果使用并行流,则无法使用AtomicInteger
的方法。
答案 1 :(得分:2)
我会将分类与打印分开。
排序:
List<Team> sorted = table.values().stream()
.sorted(Comparator.comparing(Team::getPoints)
.thenComparing(Team::goalDifference)
.reversed()
.thenComparing(Team::getName))
.collect(Collectors.toList());
印刷:
String table = IntStream.range(0, sorted.size())
.mapToObj(i -> String.format("%2d%s %-15s%5d%5d%5d%5d%5d",
i, ".",
sorted.get(i).getName(),
sorted.get(i).getPlayed(),
sorted.get(i).getWins(),
sorted.get(i).getDraws(),
sorted.get(i).getLosses(),
sorted.get(i).getPoints()))
.collect(Collectors.joining("\n"));
如果Team
类有一个接受位置并返回格式化字符串的方法,则可以改进:
public String formatWithPosition(int position) {
return String.format("%2d%s %-15s%5d%5d%5d%5d%5d",
position, ".",
name, played, wins, draws, losses, points);
}
然后,您可以按如下方式使用它:
String table = IntStream.range(0, sorted.size())
.mapToObj(Team::formatWithPosition)
.collect(Collectors.joining("\n"));