【问题标题】:Optimize method by reducing amout of code/operations on list通过减少列表中的代码/操作数量来优化方法
【发布时间】:2019-07-03 08:00:17
【问题描述】:

我想通过将我的操作合并为一个来减少开销,但似乎不太清楚如何在没有错误的情况下完成我的代码

目前我有这个工作的代码:

public Map<String, Invoice> initialize(List<String> paths) {
    List<Invoice> invoices = paths
        .stream()
        .map(Invoice::new)
        .collect(Collectors.toList());

    invoices
        .forEach(e -> {
            e.setInvoiceInputStream(reader(e.getInvoicePath()));
            e.setInvoiceId(invoiceFinder.getInvoiceId(e.getInvoiceInputStream()));
        });

    Map<String, Invoice> invoiceMap = invoices
        .stream()
        .collect(
                Collectors.toMap(
                        e -> e.getInvoiceId(),
                        e -> e)
                );

return invoiceMap;

但是,执行此代码 3 次似乎是在浪费时间。 如果我尝试一些不同的东西,比如我得到错误:

return invoicePaths
    .stream()
    .map(Invoice::new)
    .collect(
        Collectors.collectingAndThen(
            Collectors.toList(), list -> {
                list
                    .forEach(e -> {
                        e.setInvoiceInputStream(reader(e.getInvoicePath()));
                        e.setInvoiceId(invoiceFinder.getInvoiceId(e.getInvoiceInputStream()));
});

Invoice 类中的构造函数:

public Invoice(String invoicePath) {
    this.invoicePath = invoicePath;
}

如何通过优化代码来减少开销?

【问题讨论】:

  • “但是,执行此代码 3 次似乎是在浪费时间。”您是否对此进行了基准测试以确认它实际上是一个问题?需要多长时间,有多少条路径?
  • 这个问题更适合codereview.stackexchange.com
  • 你有没有想过改变你的数据模型而不是方法?创建一个部分初始化的Invoice(需要以某种方式从额外服务中检索其 Id)并存储一个外部创建的 InputStream 看起来很奇怪。
  • @sfiss 你的怀疑是对的。它指出了更可疑的事情,显然InputStream(或者实际上是Reader)被视为对象的属性,而操作看起来像是在使用它。

标签: java java-8


【解决方案1】:
 paths
    .stream()
    .map(Invoice::new)
    .map(e -> {
           e.setInvoiceInputStream(reader(e.getInvoicePath()));
           e.setInvoiceId(invoiceFinder.getInvoiceId(e.getInvoiceInputStream()));
           return e;

    })
    .collect(Collectors.toMap(
                  Invoice::getInvoiceId,
                  Function.identity())
            );

我希望我没有遗漏任何括号...

想一想,你只是收集到List&lt;Invoice&gt; invoicesforEach 他们并改变一些东西——这不是Stream::map 操作吗?之后,您将 collecting 到 Map => 之后继续流管道。

【讨论】:

  • 我已经添加了上面的评论,但map 通常不应该改变元素。
  • @sfiss 为什么不呢?这不是破坏流源完整性的更改 - 所以这不仅仅是好的
  • 我以为map的合同提到了它,但它只提到了non-interference(另见stackoverflow.com/questions/32837415/…)。所以我想改变元素是好的,即使我总是尽量远离这种情况,如果可能和合理的话。也许是因为状态突变和函数式编程(这是我最常使用map 的范例)不能很好地结合在一起。
  • 通过组合两个 map 调用可以轻松删除突变,因为突变对象只是在上一步中创建的。虽然它并没有什么区别,因为对象本身不是不可变的......
【解决方案2】:

看起来你在中间循环中没有做任何有用的事情——为什么不把它放在例如地图?

public Map<String, Invoice> initialize(List<String> paths) {
    return paths
        .stream()
        .map(path -> {
            Invoice e = new Invoice(path);
            e.setInvoiceInputStream(reader(e.getInvoicePath()));
            e.setInvoiceId(invoiceFinder.getInvoiceId(e.getInvoiceInputStream()));
            return e;
        })
        .collect(
                Collectors.toMap(
                        e -> e.getInvoiceId(),
                        e -> e)
                );
}```

【讨论】:

    猜你喜欢
    • 2017-04-19
    • 1970-01-01
    • 2011-06-01
    • 2021-03-19
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 2018-08-27
    相关资源
    最近更新 更多