繁体   English   中英

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

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

这里的任务是练习 Maps & Collections。

我们有 2 个类,其属性在括号中

第一个 Class:客户端(字符串名称、字符串姓氏、Integer 年龄、BigDecimal 现金)

下面是 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"))
);

第 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

问题

  1. 如何创建具有这种属性的购物 class
  2. 如何使用随机数据在 Main 中创建此 Shopping class 的实例以进行练习?

我做了什么-> 当前行为

  1. 单独的 class 购物创建:

代码

public class Shopping {

    private Map<Client, Map<Product,Integer>> quantitiesOfProductsBoughtByClient;
  1. Main 中的代码从 Shopping class 创建随机 object -> 正在尝试差异组合,但仍然失败

代码

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

顺便说一句,我试图找到类似的问题,但没有找到,

这是一个作为起点的示例,其中有一个方法randomProductMap接受产品列表,打乱该列表,获取随机数量的产品并生成带有随机产品数量的 map。 注意:我使用 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;
        
    }
}

已编辑

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

上面的方法应该给你花费最多的客户。 简要总结那里发生了什么:迭代quantitiesOfProductsBoughtByClient quantityOfProductsBoughtByClient 收集到 map 保持客户为关键,并将每个产品的价格乘以数量和总和,最后通过迭代得到的 map使用Stream.max

虽然以上将按要求返回客户,但您不会获得其他信息,例如他到底花了多少钱。 因此,我建议您将该方法的返回值更改为Map.Entry<Client, BigDecimal>以获得客户和总支出。 为此,只需省略最后一个.getKey();

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

甚至更简单,只需将 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)
                 ));                            
     }

然后,您可以使用最大或最小支出来获取客户,例如:

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     
       

已解决,非常感谢帮助 //s1 - 新 map 创建

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

//将值添加到 map

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

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