如何使用 Lambda 解析字符串列表并将值添加到映射 <String,Integer>
How To Parse A List Of Strings And Add Values to a Map<String,Integer> Using Lambdas
在我的控制台项目中,我在一行中收到输入 {String resource} {int quantity}(可以收到多对示例:3 Motes 5 stones 5 Shards
我的目标是重构 while 循环的主体以使用尽可能多的 lambda。
我很想减少大量的 if-else 语句并使用谓词,但我是一个新手,我更想寻找其他我可以尝试的指针。
我已经查看了收集器的 javadoc,Arrays.stream() 并通读了 Oracle JDK 8 lambdas 和函数式编程中的教程,但显然需要更多实际示例。
目标是获得 250 个资源用于其中一个传奇地图键并停止程序。
我用 Scanner 解析这些值,用一个空格分隔并按如下方式实现我的逻辑:
private final static int REQUIRED_QUANTITY = 250;
private static boolean gameOver = false;
Map<String, String> legendary = new HashMap<>();
legendary.put("shards", "Shadowmourne");
legendary.put("fragments", "Valanyr");
legendary.put("motes", "Dragonwrath");
Map<String, Integer> resources = new HashMap<>();
while (true) {
String[] loot = scanner.nextLine().toLowerCase().split(" ");
String material = null;
int quantity = 0;
for (int i = 0; i < loot.length; i++) {
if (i % 2 != 0) {
material = loot[i];
} else {
quantity = Integer.parseInt(loot[i]);
}
if (material != null && quantity != 0) {
if (resources.containsKey(material.toLowerCase())) {
resources.replace(material, resources.get(material) + quantity);
}
resources.putIfAbsent(material.toLowerCase(), quantity);
material = null;
quantity = 0;
}
}
resources.forEach((s, integer) -> {
if (integer > REQUIRED_QUANTITY) {
System.out.println("Legendary obtained: " + legendary.get(s));
gameOver = true;
}
});
我做了一些修改。
- 仅对 2 个值使用 for 循环。一次只处理一行。
- 使用
compute
处理更新地图
- 放入占位符以检查正确的资源(输入时可能拼写错误。
private final static int REQUIRED_QUANTITY = 250;
private static boolean gameOver = false;
Map<String, String> legendary = new HashMap<>();
legendary.put("shards", "Shadowmourne");
legendary.put("fragments", "Valanyr");
legendary.put("motes", "Dragonwrath");
Map<String, Integer> resources = new HashMap<>();
Scanner scanner = new Scanner(System.in);
while (!gameOver) {
String[] loot =
scanner.nextLine().toLowerCase().split("\s+");
for (int i = 0; i < loot.length; i+=2) {
String material = loot[i+1];
if (!legendary.containsKey(material)) {
// do some error processing
}
int quantity = Integer.parseInt(loot[i]);
// you may want to catch exception here.
resources.compute(material.toLowerCase(),
(k, v) -> v == null ? quantity : v + quantity);
}
resources.forEach((s, integer) -> {
if (integer > REQUIRED_QUANTITY) {
System.out.println("Legendary obtained: "
+ legendary.get(s));
gameOver = true;
}
});
}
我已将您提供的代码封装到 class。
映射resources
重命名并更改为实例变量Map<String, Integer> resourceToQuantity
。标志 gameOver
也被制成实例变量。
主要 game-logic 位于 collectResources()
方法中,主要增强功能在此处进行:
- 标志
gameOver
用作 while loop
的退出条件;
nested for loop
的条件已更改;
- 缩短了
for loop
,删除了 if/else
语句;
- 变量
quantity
和 material
的范围已缩小;
- 在循环的每次迭代中合并
quantity
并根据 REQUIRED_QUANTITY
; 检查总数
- 如果这种情况是肉标志
gameOver
被设置为 true
并且 game-loop 退出。
- 正在打印收集到的资源。
public class LootHunter {
private final static int REQUIRED_QUANTITY = 250;
private static final Map<String, String> legendary = Map.of(
"shards", "Shadowmourne",
"fragments", "Valanyr",
"motes", "Dragonwrath"
);
private final Map<String, Integer> resourceToQuantity;
private boolean gameOver;
public LootHunter() {
this.resourceToQuantity = new HashMap<>();
}
public void collectResources() {
while (!gameOver) {
Scanner scanner = new Scanner(System.in);
String[] loot = scanner.nextLine().toLowerCase().split(" ");
for (int i = 0; i < loot.length - 1; i += 2) {
int quantity = Integer.parseInt(loot[i]);
String material = loot[i + 1];
int totalQuantity = resourceToQuantity.merge(material, quantity, Integer::sum); // merges quantities and returns the sum
if (totalQuantity > REQUIRED_QUANTITY) {
System.out.printf("You win! %d of %s have been collected.%n", totalQuantity, material);
System.out.println("Legendary item obtained: " + legendary.get(material));
gameOver = true;
break;
}
}
}
printAllResources(); // prints all the collected resources
}
public void printAllResources() {
System.out.println("List of resources collected:");
resourceToQuantity.forEach((material, quantity) ->
System.out.printf("%s: %d%n", material, quantity));
}
public static void main(String[] args) {
LootHunter lootHunter = new LootHunter();
lootHunter.collectResources();
}
}
输入:
"30 shards 10 fragments 50 motes 80 fragments 70 shards 180 fragments"
输出
You win! 270 of fragments have been collected.
Legendary item obtained: Valanyr
List of resources collected:
shards: 100
motes: 50
fragments: 270
在我的控制台项目中,我在一行中收到输入 {String resource} {int quantity}(可以收到多对示例:3 Motes 5 stones 5 Shards
我的目标是重构 while 循环的主体以使用尽可能多的 lambda。 我很想减少大量的 if-else 语句并使用谓词,但我是一个新手,我更想寻找其他我可以尝试的指针。
我已经查看了收集器的 javadoc,Arrays.stream() 并通读了 Oracle JDK 8 lambdas 和函数式编程中的教程,但显然需要更多实际示例。
目标是获得 250 个资源用于其中一个传奇地图键并停止程序。 我用 Scanner 解析这些值,用一个空格分隔并按如下方式实现我的逻辑:
private final static int REQUIRED_QUANTITY = 250;
private static boolean gameOver = false;
Map<String, String> legendary = new HashMap<>();
legendary.put("shards", "Shadowmourne");
legendary.put("fragments", "Valanyr");
legendary.put("motes", "Dragonwrath");
Map<String, Integer> resources = new HashMap<>();
while (true) {
String[] loot = scanner.nextLine().toLowerCase().split(" ");
String material = null;
int quantity = 0;
for (int i = 0; i < loot.length; i++) {
if (i % 2 != 0) {
material = loot[i];
} else {
quantity = Integer.parseInt(loot[i]);
}
if (material != null && quantity != 0) {
if (resources.containsKey(material.toLowerCase())) {
resources.replace(material, resources.get(material) + quantity);
}
resources.putIfAbsent(material.toLowerCase(), quantity);
material = null;
quantity = 0;
}
}
resources.forEach((s, integer) -> {
if (integer > REQUIRED_QUANTITY) {
System.out.println("Legendary obtained: " + legendary.get(s));
gameOver = true;
}
});
我做了一些修改。
- 仅对 2 个值使用 for 循环。一次只处理一行。
- 使用
compute
处理更新地图 - 放入占位符以检查正确的资源(输入时可能拼写错误。
private final static int REQUIRED_QUANTITY = 250;
private static boolean gameOver = false;
Map<String, String> legendary = new HashMap<>();
legendary.put("shards", "Shadowmourne");
legendary.put("fragments", "Valanyr");
legendary.put("motes", "Dragonwrath");
Map<String, Integer> resources = new HashMap<>();
Scanner scanner = new Scanner(System.in);
while (!gameOver) {
String[] loot =
scanner.nextLine().toLowerCase().split("\s+");
for (int i = 0; i < loot.length; i+=2) {
String material = loot[i+1];
if (!legendary.containsKey(material)) {
// do some error processing
}
int quantity = Integer.parseInt(loot[i]);
// you may want to catch exception here.
resources.compute(material.toLowerCase(),
(k, v) -> v == null ? quantity : v + quantity);
}
resources.forEach((s, integer) -> {
if (integer > REQUIRED_QUANTITY) {
System.out.println("Legendary obtained: "
+ legendary.get(s));
gameOver = true;
}
});
}
我已将您提供的代码封装到 class。
映射resources
重命名并更改为实例变量Map<String, Integer> resourceToQuantity
。标志 gameOver
也被制成实例变量。
主要 game-logic 位于 collectResources()
方法中,主要增强功能在此处进行:
- 标志
gameOver
用作while loop
的退出条件; nested for loop
的条件已更改;- 缩短了
for loop
,删除了if/else
语句; - 变量
quantity
和material
的范围已缩小; - 在循环的每次迭代中合并
quantity
并根据REQUIRED_QUANTITY
; 检查总数
- 如果这种情况是肉标志
gameOver
被设置为true
并且 game-loop 退出。 - 正在打印收集到的资源。
public class LootHunter {
private final static int REQUIRED_QUANTITY = 250;
private static final Map<String, String> legendary = Map.of(
"shards", "Shadowmourne",
"fragments", "Valanyr",
"motes", "Dragonwrath"
);
private final Map<String, Integer> resourceToQuantity;
private boolean gameOver;
public LootHunter() {
this.resourceToQuantity = new HashMap<>();
}
public void collectResources() {
while (!gameOver) {
Scanner scanner = new Scanner(System.in);
String[] loot = scanner.nextLine().toLowerCase().split(" ");
for (int i = 0; i < loot.length - 1; i += 2) {
int quantity = Integer.parseInt(loot[i]);
String material = loot[i + 1];
int totalQuantity = resourceToQuantity.merge(material, quantity, Integer::sum); // merges quantities and returns the sum
if (totalQuantity > REQUIRED_QUANTITY) {
System.out.printf("You win! %d of %s have been collected.%n", totalQuantity, material);
System.out.println("Legendary item obtained: " + legendary.get(material));
gameOver = true;
break;
}
}
}
printAllResources(); // prints all the collected resources
}
public void printAllResources() {
System.out.println("List of resources collected:");
resourceToQuantity.forEach((material, quantity) ->
System.out.printf("%s: %d%n", material, quantity));
}
public static void main(String[] args) {
LootHunter lootHunter = new LootHunter();
lootHunter.collectResources();
}
}
输入:
"30 shards 10 fragments 50 motes 80 fragments 70 shards 180 fragments"
输出
You win! 270 of fragments have been collected.
Legendary item obtained: Valanyr
List of resources collected:
shards: 100
motes: 50
fragments: 270