深度复制列表元素和递归 – Java

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

Deep Copy of List element and recursion - java

问题

我有一个名为Trade的类,有三个参数(amountdescriptiondate)。每笔交易的amount不能大于maxAmount

我有很多交易保存在ListToSend中,其中一些金额超过了maxAmount限制,所以我需要在发送列表之前将这些交易拆分成多个交易。

我考虑使用两个列表,原始的ListToSend和一个名为tradesToSplit的列表。
基本上我想要:

  1. ListToSend中的每个可拆分交易移动到tradesToSplit中。
  2. 然后我想循环遍历tradesToSplit,对其中的每笔交易进行以下操作:
    • 调用一个名为recursiveMethod的方法,该方法将金额除以2,并且:
      • 如果amount/2不大于maxAmount
        • 然后我创建一个newTrade,它实质上是原始交易的深拷贝,然后将newTrade的金额设置为originalAmount/2
        • 否则,继续通过调用recursiveMethod来继续分割金额。

但是我卡在这里,因为我不知道如何在多次调用recursiveMethod后编辑原始交易。

有没有更好的方法来实现我想做的事情?

英文:

I have a Trade class with 3 parameters (amount, description, date). The amount of each trade cannot be greater than maxAmount.

I have many trades saved in a ListToSend, and some of the amounts exceed the maxAmount limit, so I need to split those trades into multiple trades before sending the list.

I thought about working with two lists, my original ListToSend and a tradesToSplit list.
Basically I want to:

  1. Move each splitableTrade from ListToSend to tradesToSplit.
  2. Then I want to loop over tradesToSplit and for every trade in there :
    • I call a recursiveMethod that is going to divide the amount by 2 and:
      • if amount/2 is not greater than maxAmount :
        • Then I create a newTrade, which is essentially a deep copy of the initial trade, and I set the newTrade amount to be originalAmount/2.
        • if not, I keep dividing the amount by calling recursiveMethod

But I'm stuck here as I have no idea how to edit the original trade after many iteration of recursiveMethod.

Is there a better way to achieve what I'm trying to do ?

答案1

得分: 2

在面向对象编程中,建议将对象保持为不可变,因为不可变对象天生是线程安全的,更容易调试(您可以共享对象引用而不必担心意外或未授权的更改),等等。

对于你的情况,我建议创建一个名为splitTrade的函数,它会接受一个任意amount的交易,并返回一个交易列表,其中每个amount都小于maxAmount

以下是一些伪Java代码:

private List<Trade> splitTrade(Trade trade, List<Trade> acc) {
  if (trade.getAmount() > Trade.MAX_AMOUNT) {
    Trade trade1 = new Trade(Trade.MAX_AMOUNT, trade.getDescription(), trade.getDate());
    Trade trade2 = new Trade(trade.getAmount() - Trade.MAX_AMOUNT, trade.getDescription(), trade.getDate());
    acc.add(trade1);
    return splitTrade(trade2, acc);
  } else {
    acc.add(trade);
    return acc;
  }
}

public List<Trade> splitAllTrades(List<Trade> listToSend) {
  return listToSend.stream().flatMap((t) -> splitTrade(t, new ArrayList<Trade>()).stream().toList();
}

不使用lambda语法的版本:

public List<Trade> splitAllTrades(List<Trade> listToSend) {
  List<Trade> validTrades = new ArrayList<>();
  for (Trade trade: listToSend) {    
    validTrades.addAll(splitTrade(trade, new ArrayList<Trade>()));
  }
  return validTrades;
}
英文:

in OOP it is recommended to keep objects immutable because immutable objects are inherently thread-safe, easier to debug (you can share the object reference without worrying about unexpected or unauthorized changes), etc.

In your case I would create a function splitTrade that would take a trade of any amount and return a list of trade where each amount is less than maxAmount.

Here is some pseudo java code:

private List&lt;Trade&gt; splitTrade(Trade trade, List&lt;Trade&gt; acc) {
  if (trade.getAmount() &gt; Trade.MAX_AMOUNT) {
    Trade trade1 = new Trade(Trade.MAX_AMOUNT, trade.getDescription(), trade.getDate());
    Trade trade2 = new Trade(trade.getAmount() - Trade.MAX_AMOUNT, trade.getDescription(), trade.getDate());
    acc.add(trade1);
    return splitTrade(trade2, acc);
  } else {
    acc.add(trade);
    return acc;
  }
}

public List&lt;Trade&gt; splitAllTrades(List&lt;Trade&gt; listToSend) {
  return listToSend.stream().flatMap((t) -&gt; splitTrade(t, new ArrayList&lt;Trade&gt;()).stream().toList();
}

without the lambda syntax:

public List&lt;Trade&gt; splitAllTrades(List&lt;Trade&gt; listToSend) {
  List&lt;Trade&gt; validTrades = new ArrayList&lt;&gt;();
  for (Trade trade: listToSend) {    
    validTrades.addAll(splitTrade(trade, new ArrayList&lt;Trade&gt;()));
  }
  return validTrades;
}

答案2

得分: 1

潜在的解决方案是在Trade类内部创建一个生成符合条件的交易流的方法:

public class Trade {
    ...
    public Stream<Trade> streamLegalTrades() {
        if (amount < maxAmount)
            return Stream.of(this);

        Trade halfTrade = new Trade(amount / 2, ...);
        return Stream.of(halfTrade, halfTrade)
            .flatMap(Trade::streamLegalTrades);
    }
}

如果你对流不熟悉,上述语句可能有点令人困惑。但它基本上会生成2个新交易,然后为每个交易生成一个合法交易流。

然后,这使得将交易列表转换为所需格式变得很简单:

tradeList.stream().flatMap(Trade::streamLegalTrades).toList();
英文:

A potential solution would be to have a method inside Trade that generates a stream of trades that satisfy the criteria:

public class Trade {
    ...
    public Stream&lt;Trade&gt; streamLegalTrades() {
        if (amount &lt; maxAmount)
            return Stream.of(this);

        Trade halfTrade = new Trade(amount / 2, ...);
        return Stream.of(halfTrade, halfTrade)
            .flatMap(Trade::streamLegalTrades);
    }
}

If you're not familiar with streams then that statement might be a bit confusing. But it essentially produces 2 new trades and then produces a stream of legal trades for each of those.

This then makes it trivial to convert your list of trades:

tradeList.stream().flatMap(Trade::streamLegalTrades).toList();

huangapple
  • 本文由 发表于 2023年3月10日 01:04:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687798.html
匿名

发表评论

匿名网友

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

确定