簡體   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