简体   繁体   English

Java - 在另一个 Map 中创建 Map 时出现问题

[英]Java - Problems creating a Map inside another Map

I'm trying to create a program that keeps track of a bunch of different Strings, and "ties them together" with the current user's entered name (another String), meaning every person should have their own wallets.我正在尝试创建一个程序来跟踪一堆不同的字符串,并将它们与当前用户输入的名称(另一个字符串)“联系在一起”,这意味着每个人都应该有自己的钱包。 I tried to do this using a Map inside another Map, but this is where my brain overloads.我尝试在另一个 Map 中使用 Map 来做到这一点,但这是我大脑超负荷的地方。 How do I tie every wallet to the correct name and then display all of that?我如何将每个钱包与正确的名称联系起来,然后显示所有这些? The comment in my code gives a good example of it.我的代码中的注释就是一个很好的例子。 Here is what I have so far:这是我到目前为止所拥有的:

    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<>());

This returns new HashSet<>() if there is no mapping for name but it does not add that to the map.如果没有name映射,则返回new HashSet<>() ,但不会将其添加到 map。 What you want is .computeIfAbsent , which will just return the mapping that goes with name , but if it is not there at all, it evaluates your lambda and then adds that to the map and then returns that:你想要的是.computeIfAbsent ,它只会返回与name一起的映射,但如果它根本不存在,它会评估你的 lambda 然后将其添加到 map 然后返回:

Set<Long> deposits = walletTracker.computeIfAbsent(name, k -> new HashSet<>());

That's 'lambda' syntax - you don't write an expression that resolves to a new hashset, you write an expression that resolves to a function that produces a new hashset when provided with the key (which we don't need here, and is equal to name anyway).那是'lambda'语法 - 你不写一个解析为新哈希集的表达式,你写一个解析为 function 的表达式,当提供密钥时产生一个新的哈希集(我们在这里不需要,并且是无论如何都等于name )。

Java-esque strategy here is to make a Wallet class at least.这里的 Java 式策略是至少制作一个Wallet class。 In general, once you start putting <> inside `<>, especially if you're 3 levels deep, stop, and start writing classes instead.通常,一旦您开始将<>放入 `<> 中,尤其是当您达到 3 级深度时,请停止并开始编写类。

That should be a Map<String, Wallet> and a Map<String, Person> or whatnot.那应该是Map<String, Wallet>Map<String, Person>之类的。

Here's what I found & noticed:这是我发现并注意到的:

  • The if(!firstTime) {} block should be within the for loop, so that it actually prints on every iteration. if(!firstTime) {}块应该在 for 循环中,以便它在每次迭代时实际打印。
  • You attempt to use walletTracker.getOrDefault(name, new HashSet<>());您尝试使用walletTracker.getOrDefault(name, new HashSet<>()); , but the name variable is not the correct variable to use here. ,但name变量不是在这里使用的正确变量。 You should be using the wallet input variable.您应该使用wallet输入变量。

Here is my "print it out" code, that matches your recommended formatting:这是我的“打印出来”代码,与您推荐的格式相匹配:

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])));
    });
});

Outside of this, the code you used to actually populate the map(s) is correct.除此之外,您用于实际填充地图的代码是正确的。

@rzwitserloot Made some good points about using OOP to your advantage, and I would recommend those suggestions as well. @rzwitserloot 提出了一些关于使用 OOP 对您有利的观点,我也会推荐这些建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM