简体   繁体   English

将对象映射到多个属性 (Java)

[英]Mapping Object to Multiple Attributes (Java)

learning about lambdas and streams in my java class and trying to get this one specific part figured out.在我的 Java 类中学习 lambdas 和流,并试图弄清楚这一特定部分。

Here is our assignment: Use the class, Invoice, provided to create an array of Invoice objects.这是我们的任务:使用提供的类 Invoice 创建一个 Invoice 对象数组。 Class Invoice includes four instance variables;类 Invoice 包括四个实例变量; partNumber (type String), partDescription (type String), quantity of the item being purchased (type int0, and pricePerItem (type double). Perform the following queries on the array of Invoice objects and display the results: partNumber(String类型)、partDescription(String类型)、购买的商品数量(int0类型、pricePerItem(double类型))对Invoice对象数组进行如下查询并显示结果:

a.一种。 Use streams to sort the Invoice objects by partDescription, then display the results.使用流按 partDescription 对 Invoice 对象进行排序,然后显示结果。

b.Use streams to sort the Invoice objects by pricePerItem, then display the results.使用流按 pricePerItem 对 Invoice 对象进行排序,然后显示结果。

c. C。 Use streams to map each Invoice to its partDescription and quantity, sort the results by quantity, then display the results使用流将每个 Invoice 映射到它的 partDescription 和数量,按数量对结果进行排序,然后显示结果

d. d. Use streams to map each Invoice to its partDescription and the value of the Invoice (ie, quantity * pricePerItem).使用流将每个 Invoice 映射到它的 partDescription 和 Invoice 的值(即数量 * pricePerItem)。 Order the results by Invoice value.按发票值对结果进行排序。

e. e. Modify Part (d) to select the Invoice values in the range $200.00 to $500.00.修改部分 (d) 以在 $200.00 到 $500.00 范围内选择发票值。

f. F。 Find any one Invoice in which the partDescription contains the word “saw”.查找 partDescription 中包含“saw”一词的任何一张发票。

Where I'm at: So I've got a) and b) down but I'm a little confused with part c).我在哪里:所以我有 a) 和 b),但我对 c) 部分有点困惑。 I haven't found anything online or in my book that suggests you can map an object to more than one of its own attributes.我没有在网上或我的书中找到任何建议您可以将一个对象映射到它自己的多个属性的任何内容。 I've seen one example of this project where someone created a separate function where they created a String of the two elements combined, but I don't think my professor will give points for that because he said no modifications of his Invoice class.我见过这个项目的一个例子,有人创建了一个单独的函数,在其中创建了一个由两个元素组合而成的字符串,但我认为我的教授不会为此给出分数,因为他说他的 Invoice 类没有任何修改。 I'm wondering if he wants us to use a lambda to modify the toString method of Invoice, but that doesn't quite seem right because then we technically wouldn't be mapping the object of both attributes, just mapping to one and changing its output.我想知道他是否希望我们使用 lambda 来修改 Invoice 的 toString 方法,但这似乎不太正确,因为从技术上讲,我们不会映射两个属性的对象,只是映射到一个并更改其输出。 Find his code (can't modify) below, and my code that I have so far.在下面找到他的代码(无法修改),以及我目前拥有的代码。

Professor's Code (can't be modified):教授代码(不可修改):

public class Invoice {
   private final int partNumber; 
   private final String partDescription;
   private int quantity;
   private double price;

   // constructor
   public Invoice(int partNumber, String partDescription, int quantity, double price)
   {
      if (quantity < 0) { // validate quantity
         throw new IllegalArgumentException("Quantity must be>= 0");
      }

      if (price < 0.0) { // validate price
         throw new IllegalArgumentException(
            "Price per item must be>= 0");
      }

      this.partNumber = partNumber;
      this.partDescription = partDescription;
      this.quantity = quantity;
      this.price = price;
   }

   // get part number
   public int getPartNumber() {
      return partNumber; // should validate
   } 

   // get description
   public String getPartDescription() {
      return partDescription;
   } 

   // set quantity
   public void setQuantity(int quantity) {
      if (quantity <0) { // validate quantity
         throw new IllegalArgumentException("Quantity must be>= 0");
      }

      this.quantity = quantity;
   } 

   // get quantity
   public int getQuantity() {
      return quantity;
   }

   // set price per item
   public void setPrice(double price) {
      if (price <0.0) { // validate price
         throw new IllegalArgumentException(
            "Price per item must be>= 0");
      }

      this.price = price;
   } 

   // get price per item
   public double getPrice() {
      return price;
   } 

   // return String representation of Invoice object
   @Override
   public String toString() {
      return String.format(
         "Part #: %-2d  Description: %-15s  Quantity: %-4d  Price: $%,6.2f", 
         getPartNumber(), getPartDescription(), 
         getQuantity(), getPrice());
   } 
}

**Here's my code so far: ** **这是我目前的代码:**

// import statements
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class InvoiceDriver {

    //***************************************************************
    //  Method:       developerInfo
    //  Description:  The developer information method of the program
    //  Parameters:   none
    //  Returns:      n/a
    //**************************************************************
    public static void developerInfo() {
        System.out.println("");
        System.out.println("*************************************************");
        System.out.println ("Name:    Allison Crenshaw");
        System.out.println ("Course:  ITSE 2317 Intermediate Java Programming");
        System.out.println ("Program: Five");
        System.out.println("*************************************************");
    } // End of developerInfo

    public static void main(String[] args) {
        // variables
        Invoice[] invoices = {
        new Invoice(83, "Electric sander",
                7, 57.98),
        new Invoice(24,"Power saw",
                18, 99.99),
        new Invoice(7, "Sledge hammer",
                11, 21.50),
        new Invoice(77, "Hammer",
                76, 11.99),
        new Invoice(39, "Lawn mower",
                3, 79.50),
        new Invoice(68, "Screwdriver",
                106, 6.99),
        new Invoice(56, "Jig saw",
                21, 11.00),
        new Invoice(3, "Wrench",
                34, 7.50)};

        // display developer info
        developerInfo();

        // welcome message
        System.out.println("Welcome to this Invoice Program.");
        System.out.println("This program receives invoice information " +
                "and displays");
        System.out.println("the info based on various sorts using lambdas " +
                "and streams.");
        System.out.println();

        // get list view of Invoices and use to stream and print
        List<Invoice> list = Arrays.asList(invoices);

        // use a st

        // a) use streams to sort the invoices by descriptions, then display
        System.out.println("Invoices sorted by description: ");
        Arrays.stream(invoices)
                .sorted(Comparator.comparing(Invoice::getPartDescription))
                .forEach(System.out::println);
        System.out.println();

        // b) use streams to sort the invoices by price, then display
        System.out.println("Invoices sorted by price: ");
        Arrays.stream(invoices)
                .sorted(Comparator.comparing(Invoice::getPrice))
                .forEach(System.out::println);
        System.out.println();

        // c) use streams to map each invoice to its description and quantity,
        //    sort the results by quantity, then display the results
        System.out.println("Invoices mapped to description and quantity " +
                "and sorted by quantity: ");
        list.stream()
                .map(Invoice::getPartDescription)
                .forEach(System.out::println);

        // d) use streams to map each invoice to its description and the
        //    value of the invoice (quantity * price) then order by value

        // e) modify part d) to select the invoice values in range $200-$500

        // f) find any one invoice in which description contains the word "saw"


    } // main

} // end InvoiceDriver

**Here's what the output is supposed to look like for part c): ** **这是 c) 部分的输出应该是什么样子:**

Invoices mapped to description and quantity:映射到描述和数量的发票:

Description: Lawn mower Quantity: 3描述:割草机数量:3

Description: Electric sander Quantity: 7描述:电动砂光机数量:7

Description: Sledge hammer Quantity: 11描述:大锤数量:11

Description: Power saw Quantity: 18描述:电锯数量:18

Description: Jig saw Quantity: 21描述:曲线锯数量:21

Description: Wrench Quantity: 34描述:扳手数量:34

Description: Hammer Quantity: 76描述:锤子数量:76

Description: Screwdriver Quantity: 106描述:螺丝刀数量:106

You can map the element to anything you want, including, for example, a String :您可以将元素映射到您想要的任何内容,例如包括String

list.
    stream().
    sorted(Comparator.comparing(Invoice::getQuantity)).
    map(invoice -> 
        String.format(
            "Description: %-15s  Quantity: %-4d", 
            invoice.getPartDescription(), 
            invoice.getQuantity()
        )
    ).
    forEach(System.out::println);

Here is the solution.这是解决方案。 Looks like you already understand streams and lambdas well.看起来您已经很了解流和 lambda 表达式了。 So, I haven't added too much explanation in the code comments.所以,我没有在代码注释中添加过多的解释。 Let me know if you need any explanations.如果您需要任何解释,请告诉我。

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class InvoiceProcessor {

    //MAIN METHOD - START HERE !!!
    public static void main(String[] args) {
        List<Invoice> invoices = getInvoices();
        System.out.println("\nQuestion A:");
        partA(invoices);
        System.out.println("\nQuestion B:");
        partB(invoices);
        System.out.println("\nQuestion C:");
        partC(invoices);
        System.out.println("\nQuestion D:");
        partD(invoices);
        System.out.println("\nQuestion E:");
        partE(invoices);
        System.out.println("\nQuestion F:");
        partF(invoices);
    }

    //Generate some sample invoices to use in our code - using lambdas and streams!
    public static List<Invoice> getInvoices(){
        List<String> partNames = Arrays.asList("Lawn mower", "Electric sander", "Sledge hammer",
                "Power saw", "Jig saw", "Wrench", "Hammer", "Screwdriver");

        List<Invoice> invoices = IntStream
                .range(0, partNames.size())
                //Use each number to generate Invoices,i.e. 1 number is MAP-ped to 1 invoice.
                .mapToObj(n -> new Invoice(n, partNames.get(n), (n%3)+1, (n+1) * 50.0))
                //Collect all the invoices in a list.
                .collect(Collectors.toList());

        return invoices;
    }

    //a. Use streams to sort the Invoice objects by partDescription, then display the results.
    public static void partA(List<Invoice> invoices){
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getPartDescription))
                .forEach(System.out::println);
    }

    //b. Use streams to sort the Invoice objects by pricePerItem, then display the results.
    public static void partB(List<Invoice> invoices){
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getPrice))
                .forEach(System.out::println);
    }

    //c. Use streams to map each Invoice to its partDescription and quantity, sort the results by quantity,
    // then display the results.
    public static void partC(List<Invoice> invoices){
        //Do we really need to do any mapping here?
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getQuantity))
                .forEach(i -> System.out.println("Description: " + i.getPartDescription() + " Quantity: " + i.getQuantity())
                );
    }

    //d. Use streams to map each Invoice to its partDescription and the value of the
    // Invoice (i.e., quantity * pricePerItem). Order the results by Invoice value.
    public static void partD(List<Invoice> invoices){
        //Do we really need to do any mapping here?
        invoices.stream()
                .sorted( Comparator.comparingDouble(i -> i.getQuantity() * i.getPrice() ) )
                .forEach(i -> System.out.println("Description: " + i.getPartDescription() + " Invoice value: " + i.getQuantity() * i.getPrice())
                );
    }

    //e. Modify Part (d) to select the Invoice values in the range $200.00 to $500.00.
    public static void partE(List<Invoice> invoices){
        invoices.stream()
                .filter(i -> 200.0 <= i.getQuantity() * i.getPrice() && i.getQuantity() * i.getPrice() <= 500.0)
                .forEach(i -> System.out.println("Description: " + i.getPartDescription() + " Invoice value: " + i.getQuantity() * i.getPrice()));
    }

    //f. Find any one Invoice in which the partDescription contains the word "saw".
    public static void partF(List<Invoice> invoices){
        Invoice saw = invoices.stream()
                .filter(i -> i.getPartDescription().contains("saw"))
                .findFirst()
                .get();
        System.out.println(saw);
    }

}

The way you have mapped the Stream , you would only be able to access the partDescription and not the quantity at the same time.您映射Stream ,您将只能同时访问partDescription而不是quantity

.map(Invoice::getPartDescription) // changed to Stream<String> from Stream<Invoice>

Use streams to map each Invoice to its partDescription and quantity, sort the results by quantity, then display the results使用流将每个 Invoice 映射到它的 partDescription 和数量,按数量对结果进行排序,然后显示结果

Thinking around to keep a tuple of both these attributes at the same time, a Map could be useful to collect the information for further processing( sorting ).考虑同时保留这两个属性的元组, Map可能有助于收集信息以进行进一步处理(排序)。 This would look like:这看起来像:

list.stream()
        .collect(Collectors.toMap(Invoice::getPartDescription,
                Invoice::getQuantity)) // map description to its quantity
        .entrySet().stream()
        .sorted(Map.Entry.comparingByValue()) // sort by quantity (values of map)
        .forEach(e -> System.out.println("Description: " + e.getKey() + " Quantity: " + e.getValue()));
  • You can follow up with a similar approach for section 'd' with a change in attributes.您可以对“d”部分使用类似的方法,并更改属性。
  • Further for section 'e' you would need to use .filter to selectively process the elements.此外,对于“e”部分,您需要使用.filter来有选择地处理元素。
  • Once you know how to filter , you need to findAny for section 'f' while you filter based on the given condition around the description.一旦你知道如何filter ,你需要findAny对部分“F”,而你过滤器的基础上围绕描述给定的条件。

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

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