Java - 在另一个地图中创建地图时出现问题
Java - Problems creating a Map inside another Map
我正在尝试创建一个程序来跟踪一堆不同的字符串,并将它们与当前用户输入的名称(另一个字符串)“联系在一起”,这意味着每个人都应该有自己的钱包。我试图在另一个地图中使用一个地图来做到这一点,但这是我的大脑超载的地方。我如何将每个钱包绑定到正确的名称然后显示所有这些?我的代码中的注释给出了一个很好的例子。这是我目前所拥有的:
Scanner sysin = new Scanner(System.in);
boolean firstTime = true;
Map<String, Set<Long>> walletTracker = new HashMap<String, Set<Long>>();
Map<String, Map<String, Set<Long>>> nameTracker = new HashMap<String, Map<String, Set<Long>>>();
if(!firstTime) {
/* Here it should display every entered name, wallet and time of deposit, like this:
Jack:
JacksWallet:
[12345], [123456], [1234567]
JacksOtherWallet:
[123], [1234]
Jonathan:
JonsWallet:
[12345678]
*/
}
for(int i = 0; i < 1;) {
System.out.print("Enter your name: ");
String name = sysin.nextLine();
System.out.print("Please enter a wallet name: ");
String wallet = sysin.nextLine();
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
deposits.add(System.currentTimeMillis());
walletTracker.put(wallet, deposits);
nameTracker.put(name, walletTracker);
System.out.println("You successfully withdrew money from "+ wallet +". Press enter to continue...");
firstTime = false;
String enter = sysin.nextLine();
}
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
如果 name
没有映射,则此 returns new HashSet<>()
但 不会 将其添加到映射中。你想要的是 .computeIfAbsent
,它只会 return 与 name
一起的映射,但如果它根本不存在,它会评估你的 lambda,然后将其添加到映射中,然后那么 return 就是:
Set<Long> deposits = walletTracker.computeIfAbsent(name, k -> new HashSet<>());
那是 'lambda' 语法 - 您不编写解析为新哈希集的表达式,而是编写解析为函数的表达式,该函数在提供密钥时生成新的哈希集(我们不这里不需要,反正等于 name
).
Java-esque 策略是至少做一个 Wallet
class。一般来说,一旦你开始将 <>
放在 `<> 中,特别是如果你有 3 层深,停止并开始写 classes。
那应该是 Map<String, Wallet>
和 Map<String, Person>
之类的。
这是我发现并注意到的:
if(!firstTime) {}
块应该在 for 循环中,以便它在每次迭代时实际打印。
- 您尝试使用
walletTracker.getOrDefault(name, new HashSet<>());
,但 name
变量不是此处使用的正确变量。您应该使用 wallet
输入变量。
这是我的“打印出来”代码,符合您推荐的格式:
nameTracker.forEach((name, wallet) -> {
System.out.println(name);
wallet.forEach((walletName, dates) -> {
System.out.printf("\t%s\n\t\t%s\n",
walletName, Arrays.toString(dates.toArray(new Long[0])));
});
});
除此之外,您用于实际填充地图的代码是正确的。
@rzwitserloot 提出了一些关于使用 OOP 的好处,我也会推荐这些建议。
我正在尝试创建一个程序来跟踪一堆不同的字符串,并将它们与当前用户输入的名称(另一个字符串)“联系在一起”,这意味着每个人都应该有自己的钱包。我试图在另一个地图中使用一个地图来做到这一点,但这是我的大脑超载的地方。我如何将每个钱包绑定到正确的名称然后显示所有这些?我的代码中的注释给出了一个很好的例子。这是我目前所拥有的:
Scanner sysin = new Scanner(System.in);
boolean firstTime = true;
Map<String, Set<Long>> walletTracker = new HashMap<String, Set<Long>>();
Map<String, Map<String, Set<Long>>> nameTracker = new HashMap<String, Map<String, Set<Long>>>();
if(!firstTime) {
/* Here it should display every entered name, wallet and time of deposit, like this:
Jack:
JacksWallet:
[12345], [123456], [1234567]
JacksOtherWallet:
[123], [1234]
Jonathan:
JonsWallet:
[12345678]
*/
}
for(int i = 0; i < 1;) {
System.out.print("Enter your name: ");
String name = sysin.nextLine();
System.out.print("Please enter a wallet name: ");
String wallet = sysin.nextLine();
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
deposits.add(System.currentTimeMillis());
walletTracker.put(wallet, deposits);
nameTracker.put(name, walletTracker);
System.out.println("You successfully withdrew money from "+ wallet +". Press enter to continue...");
firstTime = false;
String enter = sysin.nextLine();
}
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
如果 name
没有映射,则此 returns new HashSet<>()
但 不会 将其添加到映射中。你想要的是 .computeIfAbsent
,它只会 return 与 name
一起的映射,但如果它根本不存在,它会评估你的 lambda,然后将其添加到映射中,然后那么 return 就是:
Set<Long> deposits = walletTracker.computeIfAbsent(name, k -> new HashSet<>());
那是 'lambda' 语法 - 您不编写解析为新哈希集的表达式,而是编写解析为函数的表达式,该函数在提供密钥时生成新的哈希集(我们不这里不需要,反正等于 name
).
Java-esque 策略是至少做一个 Wallet
class。一般来说,一旦你开始将 <>
放在 `<> 中,特别是如果你有 3 层深,停止并开始写 classes。
那应该是 Map<String, Wallet>
和 Map<String, Person>
之类的。
这是我发现并注意到的:
if(!firstTime) {}
块应该在 for 循环中,以便它在每次迭代时实际打印。- 您尝试使用
walletTracker.getOrDefault(name, new HashSet<>());
,但name
变量不是此处使用的正确变量。您应该使用wallet
输入变量。
这是我的“打印出来”代码,符合您推荐的格式:
nameTracker.forEach((name, wallet) -> {
System.out.println(name);
wallet.forEach((walletName, dates) -> {
System.out.printf("\t%s\n\t\t%s\n",
walletName, Arrays.toString(dates.toArray(new Long[0])));
});
});
除此之外,您用于实际填充地图的代码是正确的。
@rzwitserloot 提出了一些关于使用 OOP 的好处,我也会推荐这些建议。