【问题标题】:Update a list reference inside a method更新方法内的列表引用
【发布时间】:2021-08-08 11:15:27
【问题描述】:

在 Java 中,我们不能在方法中重新分配引用。
所以以下不起作用:

class SomeClass {  
  List<PaidOrders> paidOrders;  
  List<PendingOrders> pendingOrders;  
  List<CancelledOrders> cancelledOrders;  

  private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
     List<Order> newOrders = fromOrderStatus(data);  
     currentOrderlist = newOrders;  
  } 
}

但以下方法确实有效:

class SomeClass {  
  
  private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
     List<Order> newOrders = fromOrderStatus(data);  
     currentOrderlist.clear();  
     currentOrderlist.addAll(newOrders); // <- extra linear loop  
  } 
}

问题在于第二个示例执行了一个额外的线性循环以从一个列表复制到另一个列表。

问题:
我想知道,是否有一些设计方法可以让我巧妙地替换参考? IE。以某种方式使第一个 sn-p 与参数或其他东西的一些变化一起工作?

更新
在 cmets 之后,我想澄清一下 currentOrderList 可以是 paidOrderspendingOrderscancelledOrders 中的任何一个。
process 的代码对所有类型都是相同的。

【问题讨论】:

  • 是否需要通过currentOrderlist。您从方法返回newOrders,并在调用方法时直接将其分配给currentOrderlist
  • currentOrderlist 字段吗?
  • @ScaryWombat:它已经是一个字段,但是我有多个这样的列表(但存储了不同的类型)作为成员,并且它们正在执行相同的处理,所以我需要将列表传递为避免代码重复的参数。我只是简化了帖子,也许我应该补充一下?
  • @VaibS:请同时查看上面的评论(更新后的帖子)
  • @ScaryWombat:更新帖子

标签: java list oop arraylist design-patterns


【解决方案1】:

嗯。我在这里看到两种可能性。您可以使用一些包装器对象,例如 AtomicReference(由于多线程问题可能有点过分)作为参数,然后将其设置在那里,或者您使用消费者。

在第二种情况下,您的方法如下所示:

public void process(List<OrderStatus> data, Consumer<List<Orders>> target) {
   List<Person> newOrders = fromOrderStatus(data);  
   target.accept(newOrders);  
}

然后在调用方你可以这样实现它:

process(data, e-> <<targetList>> = e);

【讨论】:

  • 如果有帮助,该方法将永远不会被多个线程调用。另外我不太明白调用代码sn-p
  • 在 sn-p 中,我将 lambda 用于预期的消费者对象。 > 我想表达的是,你必须在这个地方选择你想要更新的列表。因此,例如,您可以将其替换为paidOrders。然后在执行之后,您的paidOrders 将被设置为一个,给消费者。
  • &lt;&lt;target&gt;&gt; 列表是什么?实际语法是什么?
  • (抱歉 - 当我想换行时,我仍然总是按 Enter 键,所以我的回答起初不是很有帮助。我编辑了实际内容)
【解决方案2】:
  1. 如果您的列表将由不同的对象包装(例如 - AtomicReference),那么您将能够更改它。

    public static void doSomething(AtomicReference<List<Integer>> listAtomicReference){
        List<Integer> newIntegers = new ArrayList<>();
        listAtomicReference.set(newIntegers);
    }
    
    public static void main(String[] args) {
        AtomicReference<List<Integer>> listAtomicReference = new AtomicReference<>(Arrays.asList(4));
        doSomething(listAtomicReference);
        System.out.println(listAtomicReference.get());
    }
    

    输出:

    []
    
  2. 在类中创建一个公共成员变量。

话虽如此,我不建议走这条路。

Is premature optimization really the root of all evil?

【讨论】:

  • 这种方法中的过早优化究竟是什么?
  • @Jim “问题是第二个例子做了一个额外的线性循环来从一个列表复制到另一个。”你的用例真的有问题吗?
  • 重点是——你写的代码比我上面写的代码性能低,但可读性强。在大多数用例中,我们甚至不会注意到这两种方法之间的任何性能差异,因此我会采用您每天写的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-17
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2012-07-10
相关资源
最近更新 更多