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

huangapple go评论78阅读模式
英文:

Mapping Object to Multiple Attributes (Java)

问题

我理解你的要求,下面是翻译好的部分:

教授的代码(不能修改):

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

   // ... (其他方法的定义)

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

我的代码部分:

// import 语句

public class InvoiceDriver {
    
    // developerInfo 方法
    
    public static void main(String[] args) {
        // 变量定义
        Invoice[] invoices = {
        // Invoice 对象的实例化
        };
        
        // display developer info
        
        // 欢迎信息
        
        // 获取 Invoices 的 List 视图并使用流操作和打印
        List<Invoice> list = Arrays.asList(invoices);

        // a) 使用流按描述对发票进行排序,然后显示结果
        System.out.println("按描述排序的发票:");
        Arrays.stream(invoices)
                .sorted(Comparator.comparing(Invoice::getPartDescription))
                .forEach(System.out::println);
        System.out.println();

        // b) 使用流按价格对发票进行排序,然后显示结果
        System.out.println("按价格排序的发票:");
        Arrays.stream(invoices)
                .sorted(Comparator.comparing(Invoice::getPrice))
                .forEach(System.out::println);
        System.out.println();

        // c) 使用流将每个发票映射到其描述和数量,
        //    按数量排序,然后显示结果
        System.out.println("映射到描述和数量并按数量排序的发票:");
        list.stream()
                .map(invoice -> "Description: " + invoice.getPartDescription() +
                               " Quantity: " + invoice.getQuantity())
                .forEach(System.out::println);

        // d) 使用流将每个发票映射到其描述和发票的价值(数量 * 价格)然后按值排序

        // e) 修改部分 d) 以选择值在 $200 至 $500 范围内的发票

        // f) 找到其中一个描述中包含单词 "saw" 的发票

    }
}

预期部分 c) 的输出:

映射到描述和数量并按数量排序的发票:

Description: Lawn mower Quantity: 3

Description: Electric sander Quantity: 7

Description: Sledge hammer Quantity: 11

Description: Power saw Quantity: 18

Description: Jig saw Quantity: 21

Description: Wrench Quantity: 34

Description: Hammer Quantity: 76

Description: Screwdriver Quantity: 106

英文:

learning about lambdas and streams in my java class and trying to get this one specific part figured out.

Here is our assignment:
Use the class, Invoice, provided to create an array of Invoice objects. Class Invoice
includes four instance variables; 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:

a. Use streams to sort the Invoice objects by partDescription, then display the
results.

b. Use streams to sort the Invoice objects by pricePerItem, then display the results.

c. Use streams to map each Invoice to its partDescription and quantity, sort the
results by quantity, then display the results

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.

e. Modify Part (d) to select the Invoice values in the range $200.00 to $500.00.

f. Find any one Invoice in which the partDescription contains the word “saw”.

Where I'm at:
So I've got a) and b) down but I'm a little confused with part 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. 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. 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 &lt; 0) { // validate quantity
throw new IllegalArgumentException(&quot;Quantity must be&gt;= 0&quot;);
}
if (price &lt; 0.0) { // validate price
throw new IllegalArgumentException(
&quot;Price per item must be&gt;= 0&quot;);
}
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 &lt;0) { // validate quantity
throw new IllegalArgumentException(&quot;Quantity must be&gt;= 0&quot;);
}
this.quantity = quantity;
} 
// get quantity
public int getQuantity() {
return quantity;
}
// set price per item
public void setPrice(double price) {
if (price &lt;0.0) { // validate price
throw new IllegalArgumentException(
&quot;Price per item must be&gt;= 0&quot;);
}
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(
&quot;Part #: %-2d  Description: %-15s  Quantity: %-4d  Price: $%,6.2f&quot;, 
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(&quot;&quot;);
System.out.println(&quot;*************************************************&quot;);
System.out.println (&quot;Name:    Allison Crenshaw&quot;);
System.out.println (&quot;Course:  ITSE 2317 Intermediate Java Programming&quot;);
System.out.println (&quot;Program: Five&quot;);
System.out.println(&quot;*************************************************&quot;);
} // End of developerInfo
public static void main(String[] args) {
// variables
Invoice[] invoices = {
new Invoice(83, &quot;Electric sander&quot;,
7, 57.98),
new Invoice(24,&quot;Power saw&quot;,
18, 99.99),
new Invoice(7, &quot;Sledge hammer&quot;,
11, 21.50),
new Invoice(77, &quot;Hammer&quot;,
76, 11.99),
new Invoice(39, &quot;Lawn mower&quot;,
3, 79.50),
new Invoice(68, &quot;Screwdriver&quot;,
106, 6.99),
new Invoice(56, &quot;Jig saw&quot;,
21, 11.00),
new Invoice(3, &quot;Wrench&quot;,
34, 7.50)};
// display developer info
developerInfo();
// welcome message
System.out.println(&quot;Welcome to this Invoice Program.&quot;);
System.out.println(&quot;This program receives invoice information &quot; +
&quot;and displays&quot;);
System.out.println(&quot;the info based on various sorts using lambdas &quot; +
&quot;and streams.&quot;);
System.out.println();
// get list view of Invoices and use to stream and print
List&lt;Invoice&gt; list = Arrays.asList(invoices);
// use a st
// a) use streams to sort the invoices by descriptions, then display
System.out.println(&quot;Invoices sorted by description: &quot;);
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(&quot;Invoices sorted by price: &quot;);
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(&quot;Invoices mapped to description and quantity &quot; +
&quot;and sorted by quantity: &quot;);
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 &quot;saw&quot;
} // main
} // end InvoiceDriver

**Here's what the output is supposed to look like for part c): **

Invoices mapped to description and quantity:

Description: Lawn mower Quantity: 3

Description: Electric sander Quantity: 7

Description: Sledge hammer Quantity: 11

Description: Power saw Quantity: 18

Description: Jig saw Quantity: 21

Description: Wrench Quantity: 34

Description: Hammer Quantity: 76

Description: Screwdriver Quantity: 106

答案1

得分: 1

你可以将该元素映射到任何你想要的东西,包括例如一个 String

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

You can map the element to anything you want, including, for example, a String:

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

答案2

得分: 1

这是解决方案。看起来你已经很好地理解了流和Lambda表达式。因此,在代码注释中我没有添加太多的解释。如果你需要任何解释,请告诉我。

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 {

    // 主方法 - 从这里开始!!!
    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);
    }

    // 生成一些示例发票供我们的代码使用 - 使用Lambda和流!
    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())
                .mapToObj(n -> new Invoice(n, partNames.get(n), (n % 3) + 1, (n + 1) * 50.0))
                .collect(Collectors.toList());

        return invoices;
    }

    public static void partA(List<Invoice> invoices) {
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getPartDescription))
                .forEach(System.out::println);
    }

    public static void partB(List<Invoice> invoices) {
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getPrice))
                .forEach(System.out::println);
    }

    public static void partC(List<Invoice> invoices) {
        invoices.stream()
                .sorted(Comparator.comparing(Invoice::getQuantity))
                .forEach(i -> System.out.println("Description: " + i.getPartDescription() + " Quantity: " + i.getQuantity()));
    }

    public static void partD(List<Invoice> invoices) {
        invoices.stream()
                .sorted(Comparator.comparingDouble(i -> i.getQuantity() * i.getPrice()))
                .forEach(i -> System.out.println("Description: " + i.getPartDescription() + " Invoice value: " + i.getQuantity() * i.getPrice()));
    }

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

    public static void partF(List<Invoice> invoices) {
        Invoice saw = invoices.stream()
                .filter(i -> i.getPartDescription().contains("saw"))
                .findFirst()
                .get();
        System.out.println(saw);
    }
}
英文:

Here is the solution. Looks like you already understand streams and lambdas well. 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&lt;Invoice&gt; invoices = getInvoices();
System.out.println(&quot;\nQuestion A:&quot;);
partA(invoices);
System.out.println(&quot;\nQuestion B:&quot;);
partB(invoices);
System.out.println(&quot;\nQuestion C:&quot;);
partC(invoices);
System.out.println(&quot;\nQuestion D:&quot;);
partD(invoices);
System.out.println(&quot;\nQuestion E:&quot;);
partE(invoices);
System.out.println(&quot;\nQuestion F:&quot;);
partF(invoices);
}
//Generate some sample invoices to use in our code - using lambdas and streams!
public static List&lt;Invoice&gt; getInvoices(){
List&lt;String&gt; partNames = Arrays.asList(&quot;Lawn mower&quot;, &quot;Electric sander&quot;, &quot;Sledge hammer&quot;,
&quot;Power saw&quot;, &quot;Jig saw&quot;, &quot;Wrench&quot;, &quot;Hammer&quot;, &quot;Screwdriver&quot;);
List&lt;Invoice&gt; invoices = IntStream
.range(0, partNames.size())
//Use each number to generate Invoices,i.e. 1 number is MAP-ped to 1 invoice.
.mapToObj(n -&gt; 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&lt;Invoice&gt; 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&lt;Invoice&gt; 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&lt;Invoice&gt; invoices){
//Do we really need to do any mapping here?
invoices.stream()
.sorted(Comparator.comparing(Invoice::getQuantity))
.forEach(i -&gt; System.out.println(&quot;Description: &quot; + i.getPartDescription() + &quot; Quantity: &quot; + 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&lt;Invoice&gt; invoices){
//Do we really need to do any mapping here?
invoices.stream()
.sorted( Comparator.comparingDouble(i -&gt; i.getQuantity() * i.getPrice() ) )
.forEach(i -&gt; System.out.println(&quot;Description: &quot; + i.getPartDescription() + &quot; Invoice value: &quot; + 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&lt;Invoice&gt; invoices){
invoices.stream()
.filter(i -&gt; 200.0 &lt;= i.getQuantity() * i.getPrice() &amp;&amp; i.getQuantity() * i.getPrice() &lt;= 500.0)
.forEach(i -&gt; System.out.println(&quot;Description: &quot; + i.getPartDescription() + &quot; Invoice value: &quot; + i.getQuantity() * i.getPrice()));
}
//f. Find any one Invoice in which the partDescription contains the word &quot;saw&quot;.
public static void partF(List&lt;Invoice&gt; invoices){
Invoice saw = invoices.stream()
.filter(i -&gt; i.getPartDescription().contains(&quot;saw&quot;))
.findFirst()
.get();
System.out.println(saw);
}
}

答案3

得分: 0

你已经映射了Stream,只能同时访问partDescription而无法访问quantity

.map(Invoice::getPartDescription) // 从Stream<Invoice>更改为Stream<String>

使用流将每个发票映射到其partDescription和quantity,按quantity对结果进行排序,然后显示结果。

为了同时保留这两个属性的元组,使用Map可以很有用,以便收集进一步处理(排序)的信息。代码如下:

list.stream()
.collect(Collectors.toMap(Invoice::getPartDescription,
Invoice::getQuantity)) // 将描述映射到其数量
.entrySet().stream()
.sorted(Map.Entry.comparingByValue()) // 按数量(map的值)排序
.forEach(e -> System.out.println("Description: " + e.getKey() + " Quantity: " + e.getValue()));
  • 对于部分'd',您可以采用类似的方法进行跟进,更改属性。
  • 此外,对于部分'e',您需要使用.filter来有选择地处理元素。
  • 一旦您知道如何进行filter,在围绕描述进行过滤的给定条件下,您需要在部分'f'中使用findAny
英文:

The way you have mapped the Stream, you would only be able to access the partDescription and not the quantity at the same time.

.map(Invoice::getPartDescription) // changed to Stream&lt;String&gt; from Stream&lt;Invoice&gt;

> Use streams to map each Invoice to its partDescription and quantity,
> sort the results by quantity, then display the results

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). 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 -&gt; System.out.println(&quot;Description: &quot; + e.getKey() + &quot; Quantity: &quot; + e.getValue()));
  • You can follow up with a similar approach for section 'd' with a change in attributes.
  • Further for section 'e' you would need to use .filter to selectively process the elements.
  • Once you know how to filter, you need to findAny for section 'f' while you filter based on the given condition around the description.

huangapple
  • 本文由 发表于 2020年3月16日 13:58:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/60701000.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定