From 68e61d95070b3127abd8e31fa57268fe405cb605 Mon Sep 17 00:00:00 2001 From: Sean Gilligan Date: Fri, 15 Sep 2023 17:30:35 -0700 Subject: [PATCH] Wallet: refactor `getWatchedOutputs()` to use streams 1. Get a spliterator from the concatenated iterator 2. Use streams instead of nested loops 3. Extract `isWatchedScriptPubKey()` helper function --- .../main/java/org/bitcoinj/wallet/Wallet.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/wallet/Wallet.java b/core/src/main/java/org/bitcoinj/wallet/Wallet.java index b901be56a..6e18fea76 100644 --- a/core/src/main/java/org/bitcoinj/wallet/Wallet.java +++ b/core/src/main/java/org/bitcoinj/wallet/Wallet.java @@ -132,6 +132,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.Set; +import java.util.Spliterator; import java.util.TreeSet; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; @@ -141,6 +142,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.stream.StreamSupport; import static org.bitcoinj.base.internal.Preconditions.checkArgument; import static org.bitcoinj.base.internal.Preconditions.checkState; @@ -3500,27 +3502,28 @@ public class Wallet extends BaseTaggableObject lock.lock(); keyChainGroupLock.lock(); try { - List candidates = new LinkedList<>(); - for (Transaction tx : Iterables.concat(unspent.values(), pending.values())) { - if (excludeImmatureCoinbases && !isTransactionMature(tx)) continue; - for (TransactionOutput output : tx.getOutputs()) { - if (!output.isAvailableForSpending()) continue; - try { - Script scriptPubKey = output.getScriptPubKey(); - if (!watchedScripts.contains(scriptPubKey)) continue; - candidates.add(output); - } catch (ScriptException e) { - // Ignore - } - } - } - return candidates; + Spliterator spliterator = Iterables.concat(unspent.values(), pending.values()).spliterator(); + return StreamSupport.stream(spliterator, false) + .filter(tx -> !excludeImmatureCoinbases || isTransactionMature(tx)) + .flatMap(tx -> tx.getOutputs().stream()) + .filter(TransactionOutput::isAvailableForSpending) + .filter(this::isWatchedScriptPubKey) + .collect(StreamUtils.toUnmodifiableList()); } finally { keyChainGroupLock.unlock(); lock.unlock(); } } + private boolean isWatchedScriptPubKey(TransactionOutput output) { + try { + Script scriptPubKey = output.getScriptPubKey(); + return watchedScripts.contains(scriptPubKey); + } catch (ScriptException e) { + return false; + } + } + /** * Clean up the wallet. Currently, it only removes risky pending transaction from the wallet and only if their * outputs have not been spent.