简体   繁体   English

Map<> 中的 Map<> 作为值 -> 如何从 Map<> 创建 object,其中 value 是另一个 Map<>?

[英]Map<> in Map<> as value -> How to create object from the Map<> where value is another Map<>?

Task here is to practise Maps & Collections.这里的任务是练习 Maps & Collections。

We have 2 classes with its attributes in the brackets我们有 2 个类,其属性在括号中

1st Class: Client (String name, String lastName, Integer age, BigDecimal cash)第一个 Class:客户端(字符串名称、字符串姓氏、Integer 年龄、BigDecimal 现金)

Below list of random clients in Main下面是 Main 中的随机客户端列表

List<Client> clients = List.of(
            new Client("Ola", "Chrzaszcz", 34, new BigDecimal("200")),
            new Client("Ala", "Kowalsky", 24, new BigDecimal("4000")),
            new Client("Olaf", "Chrzaszcz", 19, new BigDecimal("3999")),
            new Client("Piotr", "Nowak", 21, new BigDecimal("2099")),
            new Client("Ola", "Szwed", 45, new BigDecimal("3000"))
);

2nd Class: Product (String name, Enum category, BigDecimal Price)第 2 个 Class:产品(字符串名称、枚举类别、BigDecimal 价格)

List<Product> products = List.of(
            new Product("Szynka", Category.A, new BigDecimal(29)),
            new Product("Ser", Category.B, new BigDecimal(22)),
            new Product("Chleb", Category.C, new BigDecimal(6)),
            new Product("Maslo", Category.D, new BigDecimal(4)),
            new Product("Kielbasa", Category.A, new BigDecimal(25)),
            new Product("Jajka", Category.A, new BigDecimal(8)),
            new Product("Szynka", Category.C, new BigDecimal(25))
);

GOAL -> EXPECTED RESULTS : in class Main create the instance of the class Shopping where attribute is a Map with <key: Client, value: Map<Product, Integer> and fill it with random data // Integer - how many products were bought GOAL -> EXPECTED RESULTS : in class Main create the instance of the class Shopping where attribute is a Map with <key: Client, value: Map<Product, Integer> and fill it with random data // Integer - how many products were bought

QUESTION :问题

  1. How to create Shopping class with such an attibute如何创建具有这种属性的购物 class
  2. How to create an instance of this Shopping class in Main with random data for practise purpose?如何使用随机数据在 Main 中创建此 Shopping class 的实例以进行练习?

WHAT I DID -> CURRENT BEHAVIOUR :我做了什么-> 当前行为

  1. Separate class Shopping created:单独的 class 购物创建:

Code代码

public class Shopping {

    private Map<Client, Map<Product,Integer>> quantitiesOfProductsBoughtByClient;
  1. Code in Main to create random object from Shopping class -> was trying diff combintation but still failed Main 中的代码从 Shopping class 创建随机 object -> 正在尝试差异组合,但仍然失败

Code代码

Map<Client, Map<Product,Integer>> s1 = new HashMap<>();
s1.put(clients.indexOf(0), new Map(products.indexOf(1),5) );

List<Shopping> productsBoughtByClient = List.of(
      new Map<Client, Map<Product,Integer>>(clients.indexOf(0), new Map<>(products.indexOf(0),5) ),
        );

Btw i tried to find similar question, but didn't find any,顺便说一句,我试图找到类似的问题,但没有找到,

Here is an example as a starting point, where there is a method randomProductMap which accepts a list of products, shuffel this list, take a random number of products and produces a map with a random count of products.这是一个作为起点的示例,其中有一个方法randomProductMap接受产品列表,打乱该列表,获取随机数量的产品并生成带有随机产品数量的 map。 Note: I used lombok to save some lines of code, remove it if not needed.注意:我使用 lombok 来保存一些代码行,如果不需要,将其删除。

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;


public class Test {

    public static void main(String[] args) {
        List<Client> clients = List.of(
                new Client("Ola", "Chrzaszcz", 34, new BigDecimal("200")),
                new Client("Ala", "Kowalsky", 24, new BigDecimal("4000")),
                new Client("Olaf", "Chrzaszcz", 19, new BigDecimal("3999")),
                new Client("Piotr", "Nowak", 21, new BigDecimal("2099")),
                new Client("Ola", "Szwed", 45, new BigDecimal("3000"))
        );
        List<Product> products = List.of(
                new Product("Szynka", Category.A, new BigDecimal(29)),
                new Product("Ser", Category.B, new BigDecimal(22)),
                new Product("Chleb", Category.C, new BigDecimal(6)),
                new Product("Maslo", Category.D, new BigDecimal(4)),
                new Product("Kielbasa", Category.A, new BigDecimal(25)),
                new Product("Jajka", Category.A, new BigDecimal(8)),
                new Product("Szynka", Category.C, new BigDecimal(25))
        );
        Map<Client,Map<Product,Integer>> myMap = 
                clients.stream().collect(Collectors.toMap(
                        Function.identity(), c -> randomProductMap(products)));

        Shopping sh = new Shopping(myMap);

        sh.getQuantitiesOfProductsBoughtByClient()
                .forEach((client, prodMap) -> {
                    System.out.println(client.getName() + " " + client.getLastName() + " bought below products");
                    prodMap.forEach((key,value) -> {
                        System.out.println("\t" + value + " x " + key.getName());
                    });
                    //Edited
                    BigDecimal total = prodMap.entrySet().stream()
                        .map(e -> e.getKey().getPrice().multiply(BigDecimal.valueOf(e.getValue())))
                        .reduce(BigDecimal.ZERO, (p,q)-> p.add(q), BigDecimal::add);
                    System.out.println("and spent total amount of: " + total);
                    //Edited
                });
    }

    public static Map<Product,Integer> randomProductMap(List<Product> products){
        List<Product> copy = new ArrayList<>(products);
        Collections.shuffle(copy);
        Random r = new Random();
        List<Product> randomSizeList = copy.subList(0, r.nextInt(products.size()) + 1);
        return randomSizeList.stream()
                .collect(Collectors.toMap(Function.identity(), p -> r.nextInt(10)+1));
    }

    @Getter
    @Setter
    @AllArgsConstructor
    @ToString
    public static class Client {
        String name;
        String lastName;
        Integer age;
        BigDecimal cash;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    @ToString
    public static class Product {
        String name;
        Enum category;
        BigDecimal Price;
    }

    public static enum Category {
        A, B, C, D;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    @ToString
    public static class Shopping{
        private Map<Client, Map<Product,Integer>> quantitiesOfProductsBoughtByClient;
        
    }
}

Edited已编辑

public Client clientWithMostExpShoping() {
    return quantitiesOfProductsBoughtByClient.entrySet()
             .stream()
             .collect(Collectors.toMap(
                     Map.Entry::getKey,  
                     entry -> entry.getValue().entrySet().stream()
                             .map(prodMap -> prodMap.getKey().getPrice().multiply(BigDecimal.valueOf(prodMap.getValue())))
                             .reduce(BigDecimal.ZERO, (prod1,prod2)-> prod1.add(prod2), BigDecimal::add)
             )).entrySet().stream()
             .max(Comparator.comparing(Map.Entry::getValue))
             .get().getKey();                            
 }

The above method should give you the client who spend the most.上面的方法应该给你花费最多的客户。 A brief summary what is going on there: iterate over the map quantitiesOfProductsBoughtByClient collect to map keeping the client as key and multiply the price of each product with quantity and sum to a total and finally get the client with most spendings by iterating over the resulting map using Stream.max .简要总结那里发生了什么:迭代quantitiesOfProductsBoughtByClient quantityOfProductsBoughtByClient 收集到 map 保持客户为关键,并将每个产品的价格乘以数量和总和,最后通过迭代得到的 map使用Stream.max

While the above will return a client as requested, you will get no additional info for example how much exactly he spent.虽然以上将按要求返回客户,但您不会获得其他信息,例如他到底花了多少钱。 Therefore I would suggest that you change the return value of the method to either Map.Entry<Client, BigDecimal> to get both client and total spendings.因此,我建议您将该方法的返回值更改为Map.Entry<Client, BigDecimal>以获得客户和总支出。 For this just leave out the last .getKey();为此,只需省略最后一个.getKey();

...
.max(Comparator.comparing(Map.Entry::getValue))
             .get();

or even simpler just return a Map<Client, BigDecimal> client to total spending map and leave the determination of the client with highes, lowest, average or whatever to the caller of the method:甚至更简单,只需将 Map<Client, BigDecimal>客户端返回到总支出 map并将客户端的确定与最高、最低、平均或其他任何内容留给方法的调用者:

public Map<Client, BigDecimal> totalSpendingsByClient() {
         return quantitiesOfProductsBoughtByClient.entrySet()
                 .stream()
                 .collect(Collectors.toMap(
                         Map.Entry::getKey,  
                         entry -> entry.getValue().entrySet().stream()
                                 .map(prodMap -> prodMap.getKey().getPrice().multiply(BigDecimal.valueOf(prodMap.getValue())))
                                 .reduce(BigDecimal.ZERO, (prod1,prod2)-> prod1.add(prod2), BigDecimal::add)
                 ));                            
     }

Then you can use to get the client with max or min spending for example like:然后,您可以使用最大或最小支出来获取客户,例如:

Map<Client, BigDecimal> clientsTotal = totalSpendingsByClient();
Client cliWithMaxTotal = clientsTotal.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue)).get().getKey();     
Client cliWithMinTotal = //the same as above just change max to min     
       

Solved, thanks a lot for help //s1 - new map creation已解决,非常感谢帮助 //s1 - 新 map 创建

Map<Client, Map<Product,Integer>> customersWithTheirShopping = new HashMap<>(); Map<Client, Map<Product,Integer>> customersWithTheirShopping = new HashMap<>();

//adding values to the map //将值添加到 map

customersWithTheirShopping.put(clients.get(0),Map.of(products.get(0),new Integer(5))); customersWithTheirShopping.put(clients.get(0),Map.of(products.get(0),new Integer(5)));

customersWithTheirShopping.put(clients.get(1),Map.of(products.get(1),6)); customersWithTheirShopping.put(clients.get(1),Map.of(products.get(1),6));

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

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