This is an automated email from the ASF dual-hosted git repository.

sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new a90cf3a8057 IGNITE-27906 Remove creating redundant collections (#7628)
a90cf3a8057 is described below

commit a90cf3a80578b2c408c25c2332d52c9c6987652a
Author: Slava Koptilin <[email protected]>
AuthorDate: Thu Mar 5 10:48:17 2026 +0200

    IGNITE-27906 Remove creating redundant collections (#7628)
---
 .../compaction/CatalogCompactionRunner.java        | 12 +--
 .../cluster/management/ItClusterManagerTest.java   |  7 +-
 .../management/raft/ItCmgRaftServiceTest.java      |  2 +-
 .../metrics/ClusterTopologyMetricsSource.java      |  2 +-
 .../management/raft/CmgRaftGroupListener.java      |  8 +-
 .../cluster/management/raft/CmgRaftService.java    |  3 +-
 .../cluster/management/raft/ValidationManager.java |  2 +-
 .../management/topology/LogicalTopologyImpl.java   | 13 ++-
 .../topology/api/LogicalTopologySnapshot.java      | 96 ++++++++++++++++++++--
 .../api/LogicalTopologySnapshotSerializer.java     |  2 +-
 .../topology/LogicalTopologyImplTest.java          |  6 +-
 .../api/LogicalTopologySnapshotSerializerTest.java |  3 +-
 .../internal/cluster/management/MockNode.java      |  3 +-
 .../internal/deployunit/DefaultNodeCallback.java   |  5 +-
 .../internal/deployunit/DeploymentManagerImpl.java |  6 +-
 .../ignite/internal/deployunit/NodesToDeploy.java  | 26 ++----
 .../metastore/ClusterEventCallbackImpl.java        | 13 +--
 .../distributionzones/ItDataNodesManagerTest.java  |  2 +-
 .../rebalance/ItRebalanceDistributedTest.java      |  2 +-
 .../distributionzones/DistributionZoneManager.java |  2 +-
 .../ItMetaStorageMultipleNodesVsStorageTest.java   |  5 +-
 .../replicator/ItAbstractColocationTest.java       |  2 +-
 .../internal/placementdriver/TopologyTracker.java  | 11 +--
 .../negotiation/LeaseAgreement.java                |  7 +-
 .../rest/cluster/ItDataNodesControllerTest.java    |  2 +-
 .../runner/app/ItIgniteNodeRestartTest.java        | 10 +--
 .../org/apache/ignite/internal/app/IgniteImpl.java |  3 +-
 .../internal/sql/api/ItSqlCreateZoneTest.java      |  8 +-
 .../engine/exec/mapping/MappingServiceImpl.java    |  8 +-
 .../ddl/ClusterWideStorageProfileValidator.java    |  2 +-
 .../engine/statistic/StatisticAggregatorImpl.java  |  5 +-
 .../engine/framework/ClusterServiceFactory.java    | 10 +--
 .../disaster/system/ItCmgDisasterRecoveryTest.java |  3 +-
 .../system/ItSystemGroupDisasterRecoveryTest.java  |  2 +-
 ...ilablePartitionsRecoveryByFilterUpdateTest.java |  5 +-
 35 files changed, 157 insertions(+), 141 deletions(-)

diff --git 
a/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
 
b/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
index c4521564770..f1d0de10000 100644
--- 
a/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
+++ 
b/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
@@ -57,7 +57,6 @@ import 
org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexStatus;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyService;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.distributionzones.rebalance.RebalanceMinimumRequiredTimeProvider;
@@ -486,7 +485,7 @@ public class CatalogCompactionRunner implements 
IgniteComponent {
                     }
 
                     Set<String> requiredNodes = result.getSecond();
-                    List<String> missingNodes = missingNodes(requiredNodes, 
topologySnapshot.nodes());
+                    List<String> missingNodes = missingNodes(requiredNodes, 
topologySnapshot);
 
                     if (!missingNodes.isEmpty()) {
                         LOG.info("Catalog compaction aborted due to missing 
cluster members [nodes={}].", missingNodes);
@@ -640,13 +639,8 @@ public class CatalogCompactionRunner implements 
IgniteComponent {
         return executor;
     }
 
-    private static List<String> missingNodes(Set<String> requiredNodes, 
Collection<LogicalNode> logicalTopologyNodes) {
-        Set<String> logicalNodeIds = logicalTopologyNodes
-                .stream()
-                .map(InternalClusterNode::name)
-                .collect(Collectors.toSet());
-
-        return 
requiredNodes.stream().filter(not(logicalNodeIds::contains)).collect(Collectors.toList());
+    private static List<String> missingNodes(Set<String> requiredNodes, 
LogicalTopologySnapshot logicalTopologySnapshot) {
+        return 
requiredNodes.stream().filter(not(logicalTopologySnapshot::hasNode)).collect(Collectors.toList());
     }
 
     private CompletableFuture<Void> invokeOnLocalReplicas(long txBeginTime, 
UUID localNodeId, ObjectIterator<Entry> entryIterator) {
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
index 1b8123071fa..edcfab41009 100644
--- 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
@@ -35,6 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -638,7 +639,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
         MockNode nonCmgNode = cluster.get(1);
         LogicalTopologyImpl nonCmgTopology = 
nonCmgNode.clusterManager().logicalTopologyImpl();
 
-        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().nodes().size() == 2, 10_000));
+        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().size() == 2, 10_000));
     }
 
     @Test
@@ -655,7 +656,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
 
         LogicalTopologyImpl nonCmgTopology = 
nonCmgNode.clusterManager().logicalTopologyImpl();
 
-        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().nodes().size() == 2, 10_000));
+        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().size() == 2, 10_000));
     }
 
     @Test
@@ -705,7 +706,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
 
     private void waitForLogicalTopology() throws InterruptedException {
         assertTrue(waitForCondition(() -> {
-            CompletableFuture<Set<LogicalNode>> logicalTopology = 
cluster.get(0).logicalTopologyNodes();
+            CompletableFuture<Collection<LogicalNode>> logicalTopology = 
cluster.get(0).logicalTopologyNodes();
 
             assertThat(logicalTopology, willCompleteSuccessfully());
 
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
index e4c0d086467..3d5b72cd020 100644
--- 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
@@ -196,7 +196,7 @@ public class ItCmgRaftServiceTest extends 
BaseIgniteAbstractTest {
             return clusterService.topologyService().localMember();
         }
 
-        private CompletableFuture<Set<LogicalNode>> logicalTopologyNodes() {
+        private CompletableFuture<Collection<LogicalNode>> 
logicalTopologyNodes() {
             return 
raftService.logicalTopology().thenApply(LogicalTopologySnapshot::nodes);
         }
 
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
index cafe1350ff7..2bf0f7af9a4 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
@@ -110,7 +110,7 @@ public class ClusterTopologyMetricsSource extends 
AbstractMetricSource<ClusterTo
         private final IntGauge clusterSize = new IntGauge(
                 "TotalNodes",
                 "Number of nodes in the logical topology",
-                () -> logicalTopology.getLogicalTopology().nodes().size());
+                () -> logicalTopology.getLogicalTopology().size());
 
         private final UuidGauge clusterId = new UuidGauge(
                 "ClusterId",
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
index 0e34814bb8c..f6b9731871e 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
@@ -25,6 +25,7 @@ import static 
org.apache.ignite.internal.util.IgniteUtils.capacity;
 
 import java.io.Serializable;
 import java.nio.file.Path;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -158,7 +159,7 @@ public class CmgRaftGroupListener implements 
RaftGroupListener {
 
     private HashSet<LogicalNode> getValidatedNodes() {
         List<LogicalNode> validatedNodes = storageManager.getValidatedNodes();
-        Set<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
+        Collection<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
 
         var result = new HashSet<LogicalNode>(capacity(validatedNodes.size() + 
logicalTopologyNodes.size()));
 
@@ -261,10 +262,7 @@ public class CmgRaftGroupListener implements 
RaftGroupListener {
     }
 
     private ValidationResult validateNode(JoinRequestCommand command) {
-        Optional<LogicalNode> previousVersion = 
logicalTopology.getLogicalTopology().nodes()
-                .stream()
-                .filter(n -> n.name().equals(command.node().name()))
-                .findAny();
+        Optional<LogicalNode> previousVersion = 
logicalTopology.getLogicalTopology().node(command.node().name());
 
         if (previousVersion.isPresent()) {
             LogicalNode previousNode = previousVersion.get();
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
index acd0c1e042d..94f07fb3e3f 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
@@ -325,8 +325,7 @@ public class CmgRaftService implements ManuallyCloseable {
 
         Set<String> currentPeers = nodeNames();
 
-        Set<String> newLearners = 
logicalTopology.getLogicalTopology().nodes().stream()
-                .map(InternalClusterNode::name)
+        Set<String> newLearners = 
logicalTopology.getLogicalTopology().nodeNames().stream()
                 .filter(name -> !currentPeers.contains(name))
                 .collect(toSet());
 
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
index 35b3bad6097..46787f05551 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
@@ -128,7 +128,7 @@ public class ValidationManager {
     }
 
     private boolean isColocationEnabledMatched(boolean 
joiningNodeColocationEnabled) {
-        Set<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
+        Collection<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
 
         return logicalTopologyNodes.isEmpty()
                 || isColocationEnabled(logicalTopologyNodes.iterator().next()) 
== joiningNodeColocationEnabled;
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
index 855a695fb7b..4dcf96861e2 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
@@ -19,12 +19,11 @@ package 
org.apache.ignite.internal.cluster.management.topology;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Comparator.comparing;
-import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
 import static org.apache.ignite.internal.util.ExceptionUtils.hasCause;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -79,6 +78,7 @@ public class LogicalTopologyImpl implements LogicalTopology {
     }
 
     private LogicalTopologySnapshot readLogicalTopology() {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-28066
         byte[] bytes = storage.get(LOGICAL_TOPOLOGY_KEY);
 
         return bytes == null ? LogicalTopologySnapshot.INITIAL
@@ -99,8 +99,7 @@ public class LogicalTopologyImpl implements LogicalTopology {
     public void putNode(LogicalNode nodeToPut) {
         LogicalTopologySnapshot snapshot = readLogicalTopology();
 
-        Map<String, LogicalNode> mapByName = snapshot.nodes().stream()
-                .collect(toMap(LogicalNode::name, identity()));
+        Map<String, LogicalNode> mapByName = new 
HashMap<>(snapshot.nodesByName());
 
         Runnable fireRemovalTask = null;
 
@@ -167,8 +166,7 @@ public class LogicalTopologyImpl implements LogicalTopology 
{
     public void removeNodes(Set<LogicalNode> nodesToRemove) {
         LogicalTopologySnapshot snapshot = readLogicalTopology();
 
-        Map<UUID, LogicalNode> mapById = snapshot.nodes().stream()
-                .collect(toMap(LogicalNode::id, identity()));
+        Map<UUID, LogicalNode> mapById = new HashMap<>(snapshot.nodesById());
 
         // Removing in a well-defined order to make sure that a command 
produces an identical sequence of events in each CMG listener.
         List<LogicalNode> sortedNodesToRemove = nodesToRemove.stream()
@@ -201,8 +199,7 @@ public class LogicalTopologyImpl implements LogicalTopology 
{
 
     @Override
     public boolean isNodeInLogicalTopology(LogicalNode needle) {
-        return readLogicalTopology().nodes().stream()
-                .anyMatch(node -> node.id().equals(needle.id()));
+        return readLogicalTopology().hasNode(needle.id());
     }
 
     private void fireNodeJoined(LogicalNode appearedNode, 
LogicalTopologySnapshot snapshot) {
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
index 79b29d93d37..b3a8931e74f 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
@@ -18,11 +18,14 @@
 package org.apache.ignite.internal.cluster.management.topology.api;
 
 import static java.util.Collections.emptySet;
+import static java.util.function.Function.identity;
 
 import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
-import org.apache.ignite.internal.tostring.IgniteToStringInclude;
+import java.util.stream.Collectors;
 import org.apache.ignite.internal.tostring.S;
 import org.jetbrains.annotations.TestOnly;
 
@@ -41,16 +44,18 @@ public class LogicalTopologySnapshot {
 
     private final long version;
 
-    @IgniteToStringInclude
-    private final Set<LogicalNode> nodes;
+    private final Map<String, LogicalNode> nodesByName;
+    private final Map<UUID, LogicalNode> nodesById;
 
     private final UUID clusterId;
 
     /** Constructor. */
     public LogicalTopologySnapshot(long version, Collection<LogicalNode> 
nodes, UUID clusterId) {
         this.version = version;
-        this.nodes = Set.copyOf(nodes);
         this.clusterId = clusterId;
+
+        this.nodesByName = 
nodes.stream().collect(Collectors.toUnmodifiableMap(LogicalNode::name, 
identity()));
+        this.nodesById = 
nodes.stream().collect(Collectors.toUnmodifiableMap(LogicalNode::id, 
identity()));
     }
 
     /**
@@ -71,8 +76,76 @@ public class LogicalTopologySnapshot {
     /**
      * Returns the nodes that comprise the logical topology.
      */
-    public Set<LogicalNode> nodes() {
-        return nodes;
+    public Collection<LogicalNode> nodes() {
+        return nodesById.values();
+    }
+
+    /**
+     * Returns the mapping of node names to the nodes that comprise the 
logical topology.
+     */
+    public Map<String, LogicalNode> nodesByName() {
+        return nodesByName;
+    }
+
+    /**
+     * Returns the mapping of node identifiers to the nodes that comprise the 
logical topology.
+     */
+    public Map<UUID, LogicalNode> nodesById() {
+        return nodesById;
+    }
+
+    /**
+     * Returns the node names that comprise the logical topology.
+     */
+    public Set<String> nodeNames() {
+        return nodesByName.keySet();
+    }
+
+    /**
+     * Returns the node identifiers that comprise the logical topology.
+     */
+    public Set<UUID> nodeIds() {
+        return nodesById.keySet();
+    }
+
+    /**
+     * Returns {@code true} if this topology snapshot contains a node with the 
given {@code id}, and {@code false} otherwise.
+     *
+     * @param nodeId Node id.
+     * @return {@code true} if this topology snapshot contains a node with the 
given {@code id}, and {@code false} otherwise.
+     */
+    public boolean hasNode(UUID nodeId) {
+        return nodesById.containsKey(nodeId);
+    }
+
+    /**
+     * Returns {@code true} if this topology snapshot contains a node with the 
given {@code nodeName}, and {@code false} otherwise.
+     *
+     * @param nodeName Node name, aka consistent id.
+     * @return {@code true} if this topology snapshot contains a node with the 
given {@code nodeName}, and {@code false} otherwise.
+     */
+    public boolean hasNode(String nodeName) {
+        return nodesByName.containsKey(nodeName);
+    }
+
+    /**
+     * Returns a node with the given {@code nodeId} in this topology snapshot.
+     *
+     * @param nodeId Node id to find.
+     * @return Node with the given {@code nodeId} in this topology snapshot.
+     */
+    public Optional<LogicalNode> node(UUID nodeId) {
+        return Optional.ofNullable(nodesById.get(nodeId));
+    }
+
+    /**
+     * Returns a node with the given {@code nodeId} in this topology snapshot.
+     *
+     * @param nodeName Node name to find.
+     * @return Node with the given {@code nodeName} in this topology snapshot.
+     */
+    public Optional<LogicalNode> node(String nodeName) {
+        return Optional.ofNullable(nodesByName.get(nodeName));
     }
 
     /**
@@ -82,8 +155,17 @@ public class LogicalTopologySnapshot {
         return clusterId;
     }
 
+    /**
+     * Returns the number of nodes in this snapshot.
+     *
+     * @return Number of nodes in this snapshot.
+     */
+    public int size() {
+        return nodesById.size();
+    }
+
     @Override
     public String toString() {
-        return S.toString(LogicalTopologySnapshot.class, this);
+        return S.toString(LogicalTopologySnapshot.class, this, "nodes", 
nodesById.values());
     }
 }
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
index e281ab91983..10bdae1031f 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
@@ -39,7 +39,7 @@ public class LogicalTopologySnapshotSerializer extends 
VersionedSerializer<Logic
     protected void writeExternalData(LogicalTopologySnapshot snapshot, 
IgniteDataOutput out) throws IOException {
         out.writeVarInt(snapshot.version());
 
-        out.writeVarInt(snapshot.nodes().size());
+        out.writeVarInt(snapshot.size());
         for (LogicalNode node : snapshot.nodes()) {
             logicalNodeSerializer.writeExternal(node, out);
         }
diff --git 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
index 6492abe0944..0d1cbed81c4 100644
--- 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
+++ 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
@@ -19,7 +19,6 @@ package 
org.apache.ignite.internal.cluster.management.topology;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.UUID.randomUUID;
-import static java.util.stream.Collectors.toList;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
@@ -217,9 +216,8 @@ class LogicalTopologyImplTest extends 
BaseIgniteAbstractTest {
 
         storage.restoreSnapshot(snapshotDir);
 
-        List<String> namesInTopology = 
topology.getLogicalTopology().nodes().stream()
-                .map(InternalClusterNode::name)
-                .collect(toList());
+        Set<String> namesInTopology = 
topology.getLogicalTopology().nodeNames();
+
         assertThat(namesInTopology, contains("node"));
     }
 
diff --git 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
index 81e88fa402e..fa49e6915dd 100644
--- 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
+++ 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
@@ -19,6 +19,7 @@ package 
org.apache.ignite.internal.cluster.management.topology.api;
 
 import static java.util.stream.Collectors.toList;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
@@ -44,7 +45,7 @@ class LogicalTopologySnapshotSerializerTest {
         LogicalTopologySnapshot restoredSnapshot = 
VersionedSerialization.fromBytes(bytes, serializer);
 
         assertThat(restoredSnapshot.version(), is(originalSnapshot.version()));
-        assertThat(restoredSnapshot.nodes(), 
equalTo(originalSnapshot.nodes()));
+        assertThat(restoredSnapshot.nodes(), 
containsInAnyOrder(originalSnapshot.nodes().toArray()));
         assertThat(restoredSnapshot.clusterId(), 
equalTo(originalSnapshot.clusterId()));
     }
 
diff --git 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
index 79883be747f..a50449cadcd 100644
--- 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
+++ 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
@@ -28,6 +28,7 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -257,7 +258,7 @@ public class MockNode {
         return workDir;
     }
 
-    CompletableFuture<Set<LogicalNode>> logicalTopologyNodes() {
+    CompletableFuture<Collection<LogicalNode>> logicalTopologyNodes() {
         return 
clusterManager().logicalTopology().thenApply(LogicalTopologySnapshot::nodes);
     }
 
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
index 748490a54e2..6dc5c82ec39 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
@@ -26,7 +26,6 @@ import java.util.stream.Collectors;
 import org.apache.ignite.deployment.DeploymentUnit;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.deployunit.metastore.DeploymentUnitStore;
 import org.apache.ignite.internal.deployunit.metastore.NodeEventCallback;
 import 
org.apache.ignite.internal.deployunit.metastore.status.UnitClusterStatus;
@@ -91,10 +90,10 @@ public class DefaultNodeCallback extends NodeEventCallback {
     public void onRemoving(String id, Version version, List<UnitNodeStatus> 
holders) {
         cmgManager.logicalTopology()
                 .thenAccept(snapshot -> {
-                    Set<String> nodes = 
snapshot.nodes().stream().map(LogicalNode::name).collect(Collectors.toSet());
                     boolean allRemoved = holders.stream()
-                            .filter(nodeStatus -> 
nodes.contains(nodeStatus.nodeId()))
+                            .filter(nodeStatus -> 
snapshot.hasNode(nodeStatus.nodeId()))
                             .allMatch(nodeStatus -> nodeStatus.status() == 
REMOVING);
+
                     if (allRemoved) {
                         deploymentUnitStore.updateClusterStatus(id, version, 
REMOVING);
                     }
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
index 6dbe43347ee..d1ce6596435 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
@@ -41,7 +41,6 @@ import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyService;
 import org.apache.ignite.internal.deployunit.UnitStatuses.UnitStatusesBuilder;
 import 
org.apache.ignite.internal.deployunit.configuration.DeploymentConfiguration;
@@ -277,13 +276,10 @@ public class DeploymentManagerImpl implements 
IgniteDeployment {
                     if (success) {
                         return cmgManager.logicalTopology()
                                 .thenCompose(logicalTopology -> {
-                                    Set<String> logicalNodes = 
logicalTopology.nodes().stream()
-                                            .map(LogicalNode::name)
-                                            .collect(Collectors.toSet());
                                     // Set OBSOLETE status only to nodes which 
are present in the topology
                                     return deploymentUnitStore.getAllNodes(id, 
version)
                                             .thenCompose(nodes -> 
allOf(nodes.stream()
-                                                    
.filter(logicalNodes::contains)
+                                                    
.filter(logicalTopology::hasNode)
                                                     .map(node -> 
deploymentUnitStore.updateNodeStatus(node, id, version, OBSOLETE))
                                                     
.toArray(CompletableFuture[]::new)))
                                             .thenApply(v -> {
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
index 901477c53de..d5cdf89306e 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
@@ -21,23 +21,18 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
+import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.deployunit.exception.InvalidNodesArgumentException;
-import org.apache.ignite.internal.network.InternalClusterNode;
 
 /**
  * Nodes for initial deploy.
  */
 public class NodesToDeploy {
-    /**
-     * Direct nodes list.
-     */
+    /** Direct nodes list. */
     private final List<String> nodesList;
 
-    /**
-     * Deploy nodes mode.
-     */
+    /** Deploy nodes mode. */
     private final InitialDeployMode deployMode;
 
     public NodesToDeploy(List<String> nodesList) {
@@ -66,10 +61,9 @@ public class NodesToDeploy {
     private CompletableFuture<Set<String>> 
extractNodesFromMode(ClusterManagementGroupManager cmgManager) {
         switch (deployMode) {
             case ALL:
-                return cmgManager.logicalTopology()
-                        .thenApply(snapshot -> snapshot.nodes().stream()
-                                .map(InternalClusterNode::name)
-                                .collect(Collectors.toUnmodifiableSet()));
+                return cmgManager
+                        .logicalTopology()
+                        .thenApply(LogicalTopologySnapshot::nodeNames);
             case MAJORITY:
             default:
                 return cmgManager.majority();
@@ -86,13 +80,11 @@ public class NodesToDeploy {
     private CompletableFuture<Set<String>> 
extractNodesFromList(ClusterManagementGroupManager cmgManager) {
         return cmgManager.majority()
                 .thenCompose(majority -> cmgManager.logicalTopology()
-                        .thenApply(snapshot -> snapshot.nodes().stream()
-                                .map(InternalClusterNode::name)
-                                .collect(Collectors.toUnmodifiableSet()))
-                        .thenApply(allNodes -> {
+                        .thenApply(snapshot -> {
                             Set<String> result = new HashSet<>(majority);
+
                             for (String node : nodesList) {
-                                if (!allNodes.contains(node)) {
+                                if (!snapshot.hasNode(node)) {
                                     throw new InvalidNodesArgumentException(
                                             "Node \"" + node + "\" is not 
present in the logical topology"
                                     );
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
index 7575ab21ee9..5cda731cc13 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
@@ -19,15 +19,11 @@ package org.apache.ignite.internal.deployunit.metastore;
 
 import static org.apache.ignite.internal.deployunit.DeploymentStatus.REMOVING;
 
-import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Collectors;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.deployunit.FileDeployerService;
 import 
org.apache.ignite.internal.deployunit.metastore.status.UnitClusterStatus;
-import org.apache.ignite.internal.deployunit.metastore.status.UnitNodeStatus;
 
 /** Listener of deployment unit cluster status changes. */
 public class ClusterEventCallbackImpl extends ClusterEventCallback {
@@ -85,15 +81,10 @@ public class ClusterEventCallbackImpl extends 
ClusterEventCallback {
 
     private void removeClusterStatus(String id, Version version, UUID opId) {
         cmgManager.logicalTopology().thenAccept(logicalTopology -> {
-            Set<String> logicalNodes = logicalTopology.nodes().stream()
-                    .map(LogicalNode::name)
-                    .collect(Collectors.toSet());
             deploymentUnitStore.getAllNodeStatuses(id, 
version).thenAccept(statuses -> {
                 boolean emptyTopology = statuses.stream()
-                        .map(UnitNodeStatus::nodeId)
-                        .filter(logicalNodes::contains)
-                        .findAny()
-                        .isEmpty();
+                        .noneMatch(unitNodeStatus -> 
logicalTopology.hasNode(unitNodeStatus.nodeId()));
+
                 if (emptyTopology) {
                     deploymentUnitStore.removeClusterStatus(id, version, opId);
                 }
diff --git 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
index ee1a89ae81a..b464c14ba75 100644
--- 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
+++ 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
@@ -63,7 +63,7 @@ class ItDataNodesManagerTest extends 
ClusterPerTestIntegrationTest {
         LogicalTopologyService logicalTopologyService = 
node.logicalTopologyService();
 
         Awaitility.waitAtMost(2, TimeUnit.SECONDS)
-                .untilAsserted(() -> assertEquals(2, 
logicalTopologyService.localLogicalTopology().nodes().size()));
+                .untilAsserted(() -> assertEquals(2, 
logicalTopologyService.localLogicalTopology().size()));
 
         waitForDataNodes(node, ZONE_NAME, Set.of(node.name()));
 
diff --git 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
index c9907b58303..bebc9a4407c 100644
--- 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
+++ 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
@@ -385,7 +385,7 @@ public class ItRebalanceDistributedTest extends 
BaseIgniteAbstractTest {
 
                     assertThat(logicalTopologyFuture, 
willCompleteSuccessfully());
 
-                    return logicalTopologyFuture.join().nodes().size() == 
NODE_COUNT;
+                    return logicalTopologyFuture.join().size() == NODE_COUNT;
                 },
                 AWAIT_TIMEOUT_MILLIS
         ));
diff --git 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
index 4c92a01031b..0ddce418aee 100644
--- 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
+++ 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
@@ -521,7 +521,7 @@ public class DistributionZoneManager extends
         }
 
         try {
-            Set<LogicalNode> logicalTopology = newTopology.nodes();
+            Collection<LogicalNode> logicalTopology = newTopology.nodes();
 
             Condition condition;
             Update update;
diff --git 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
index ec4bfc0a85c..ba60fc971dd 100644
--- 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
+++ 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.metastorage.impl;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.concurrent.CompletableFuture.allOf;
-import static java.util.stream.Collectors.toSet;
 import static 
org.apache.ignite.internal.metastorage.TestMetasStorageUtils.checkEntry;
 import static org.apache.ignite.internal.metastorage.dsl.Conditions.notExists;
 import static org.apache.ignite.internal.metastorage.dsl.Conditions.revision;
@@ -43,6 +42,7 @@ import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.lang.ByteArray;
@@ -53,7 +53,6 @@ import 
org.apache.ignite.internal.metastorage.server.KeyValueStorage;
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import org.apache.ignite.internal.metastorage.server.time.ClusterTime;
 import org.apache.ignite.internal.metastorage.server.time.ClusterTimeImpl;
-import org.apache.ignite.internal.network.InternalClusterNode;
 import org.apache.ignite.internal.raft.Peer;
 import org.apache.ignite.internal.raft.service.RaftGroupService;
 import org.junit.jupiter.api.Test;
@@ -176,7 +175,7 @@ abstract class ItMetaStorageMultipleNodesVsStorageTest 
extends ItMetaStorageMult
 
         CompletableFuture<Set<String>> logicalTopologyNodes = 
firstNode.cmgManager
                 .logicalTopology()
-                .thenApply(logicalTopology -> 
logicalTopology.nodes().stream().map(InternalClusterNode::name).collect(toSet()));
+                .thenApply(LogicalTopologySnapshot::nodeNames);
 
         assertThat(logicalTopologyNodes, willBe(Set.of(firstNode.name(), 
secondNode.name())));
 
diff --git 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
index 1bb5a4d3744..0a91aa67eb7 100644
--- 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
+++ 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
@@ -187,7 +187,7 @@ abstract class ItAbstractColocationTest extends 
IgniteAbstractTest {
 
                     assertThat(logicalTopologyFuture, 
willCompleteSuccessfully());
 
-                    return logicalTopologyFuture.join().nodes().size() == 
cluster.size();
+                    return logicalTopologyFuture.join().size() == 
cluster.size();
                 },
                 AWAIT_TIMEOUT_MILLIS
         ));
diff --git 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
index 1c1f9dd7a3e..aae6504cf5f 100644
--- 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
+++ 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
@@ -25,7 +25,6 @@ import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopolog
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.network.InternalClusterNode;
-import org.apache.ignite.internal.util.CollectionUtils;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -93,17 +92,11 @@ public class TopologyTracker {
     public @Nullable InternalClusterNode nodeByConsistentId(String 
consistentId) {
         LogicalTopologySnapshot logicalTopologySnap0 = topologySnapRef.get();
 
-        if (logicalTopologySnap0 == null || 
CollectionUtils.nullOrEmpty(logicalTopologySnap0.nodes())) {
+        if (logicalTopologySnap0 == null || logicalTopologySnap0.size() == 0) {
             return null;
         }
 
-        for (LogicalNode node : logicalTopologySnap0.nodes()) {
-            if (node.name().equals(consistentId)) {
-                return node;
-            }
-        }
-
-        return null;
+        return logicalTopologySnap0.node(consistentId).orElse(null);
     }
 
     LogicalTopologySnapshot currentTopologySnapshot() {
diff --git 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
index 83535b47a79..8ec050f6044 100644
--- 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
+++ 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
@@ -18,14 +18,11 @@
 package org.apache.ignite.internal.placementdriver.negotiation;
 
 import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toSet;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 import static org.apache.ignite.internal.util.IgniteUtils.findAny;
 
 import java.util.Set;
-import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
@@ -191,9 +188,7 @@ public class LeaseAgreement {
 
             responseFut.complete(null);
         } else if (currentTopologySnapshot != null) {
-            Set<UUID> nodeIds = 
currentTopologySnapshot.nodes().stream().map(LogicalNode::id).collect(toSet());
-
-            if (!nodeIds.contains(lease.getLeaseholderId())) {
+            if (lease.getLeaseholderId() == null || 
!currentTopologySnapshot.hasNode(lease.getLeaseholderId())) {
                 LOG.info("Lease was not negotiated because the node has left 
the logical topology [node={}, nodeId={}, group={}]",
                         lease.getLeaseholder(), lease.getLeaseholderId(), 
groupId);
 
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
index 147d111c33f..ef6af19929f 100644
--- 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
@@ -244,7 +244,7 @@ public class ItDataNodesControllerTest extends 
ClusterPerTestIntegrationTest {
         LogicalTopologyService logicalTopologyService = 
node.logicalTopologyService();
 
         Awaitility.waitAtMost(1, TimeUnit.SECONDS).untilAsserted(() ->
-                assertEquals(expectedTopologySize, 
logicalTopologyService.localLogicalTopology().nodes().size())
+                assertEquals(expectedTopologySize, 
logicalTopologyService.localLogicalTopology().size())
         );
     }
 
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 765c25f61ac..f602726acb6 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -106,7 +106,6 @@ import 
org.apache.ignite.internal.cluster.management.configuration.NodeAttribute
 import 
org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import 
org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import 
org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
-import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.components.LogSyncer;
 import org.apache.ignite.internal.configuration.ComponentWorkingDir;
 import org.apache.ignite.internal.configuration.ConfigurationModules;
@@ -1116,17 +1115,16 @@ public class ItIgniteNodeRestartTest extends 
BaseIgniteRestartTest {
         List<IgniteImpl> nodes = startNodes(3);
 
         // Here we check that node sees itself in local logical topology.
-        nodes.forEach(node -> 
assertTrue(node.logicalTopologyService().localLogicalTopology().nodes().stream().map(LogicalNode::id)
-                .collect(toSet()).contains(node.id())));
+        nodes.forEach(node -> 
assertTrue(node.logicalTopologyService().localLogicalTopology().hasNode(node.id())));
 
         // Actually we have stronger guarantees because of awaiting all nodes 
to start inside startNodes.
         // On one node (cmg leader) we will see all three nodes in local 
logical topology.
         // On the node that started second we will see at least two nodes.
         // On the third node we will see all three nodes.
         // All in all that means that in total we will see at least (3 + 2 + 
3) nodes.
-        Integer sumOfLogicalTopologyProjectionSizes =
-                nodes.stream().map(node -> 
node.logicalTopologyService().localLogicalTopology().nodes().size())
-                        .reduce(0, Integer::sum);
+        int sumOfLogicalTopologyProjectionSizes = nodes.stream()
+                .mapToInt(node -> 
node.logicalTopologyService().localLogicalTopology().size())
+                .sum();
 
         assertTrue(sumOfLogicalTopologyProjectionSizes >= 3 + 2 + 3);
     }
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 39de9eee97b..ec77e546c2d 100644
--- 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal.app;
 
 import static java.util.concurrent.TimeUnit.MINUTES;
-import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.configuration.IgnitePaths.cmgPath;
 import static 
org.apache.ignite.internal.configuration.IgnitePaths.metastoragePath;
 import static 
org.apache.ignite.internal.configuration.IgnitePaths.partitionsPath;
@@ -1735,7 +1734,7 @@ public class IgniteImpl implements Ignite {
             CompletableFuture<Void> awaitSelfInLogicalTopologyFuture,
             LogicalTopologyEventListener awaitSelfListener
     ) {
-        if 
(logicalTopologySnapshot.nodes().stream().map(LogicalNode::id).collect(toSet()).contains(id()))
 {
+        if (logicalTopologySnapshot.hasNode(id())) {
             awaitSelfInLogicalTopologyFuture.complete(null);
             logicalTopologyService.removeEventListener(awaitSelfListener);
         }
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
index 04d14234df5..56eb6282163 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
@@ -98,7 +98,7 @@ class ItSqlCreateZoneTest extends 
ClusterPerTestIntegrationTest {
         IgniteImpl node1 = unwrapIgniteImpl(cluster.startNode(1));
 
         assertTrue(waitForCondition(
-                () -> 
node1.logicalTopologyService().localLogicalTopology().nodes().size() == 2,
+                () -> 
node1.logicalTopologyService().localLogicalTopology().size() == 2,
                 10_000
         ));
 
@@ -120,17 +120,17 @@ class ItSqlCreateZoneTest extends 
ClusterPerTestIntegrationTest {
 
         // Check that Node 0 and 2 will see all three nodes in local logical 
topologies.
         assertTrue(waitForCondition(
-                () -> 
unwrapIgniteImpl(node(0)).logicalTopologyService().localLogicalTopology().nodes().size()
 == 3,
+                () -> 
unwrapIgniteImpl(node(0)).logicalTopologyService().localLogicalTopology().size()
 == 3,
                 10_000
         ));
 
         assertTrue(waitForCondition(
-                () -> 
unwrapIgniteImpl(node(2)).logicalTopologyService().localLogicalTopology().nodes().size()
 == 3,
+                () -> 
unwrapIgniteImpl(node(2)).logicalTopologyService().localLogicalTopology().size()
 == 3,
                 10_000
         ));
 
         // And we expect that node 1 won't see node 2 in its local logical 
topology.
-        assertEquals(2, 
node1.logicalTopologyService().localLogicalTopology().nodes().size());
+        assertEquals(2, 
node1.logicalTopologyService().localLogicalTopology().size());
 
         // But still we're able to create zone with extra profile on node 2 
because node 1 will try to ask CMG leader (node 0) directly over
         // the network for its up-to-date leader's local logical topology and 
check this snapshot's storage profiles that should
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
index 6d1c5645fd1..f8b8e97f6d1 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
@@ -518,7 +518,7 @@ public class MappingServiceImpl implements MappingService, 
LogicalTopologyEventL
         void update(LogicalTopologySnapshot topologySnapshot) {
             synchronized (this) {
                 if (topology.version() < topologySnapshot.version()) {
-                    topology = new 
TopologySnapshot(topologySnapshot.version(), deriveNodeNames(topologySnapshot));
+                    topology = new 
TopologySnapshot(topologySnapshot.version(), topologySnapshot.nodeNames());
                 }
 
                 if (initialTopologyFuture.isDone() || 
!topology.nodes().contains(localNodeName)) {
@@ -533,12 +533,6 @@ public class MappingServiceImpl implements MappingService, 
LogicalTopologyEventL
             return topology;
         }
 
-        private Set<String> deriveNodeNames(LogicalTopologySnapshot topology) {
-            return topology.nodes().stream()
-                    .map(LogicalNode::name)
-                    .collect(Collectors.toUnmodifiableSet());
-        }
-
         class TopologySnapshot {
             private final Set<String> nodes;
             private final long version;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
index 221615a8801..2c4e3b24599 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
@@ -104,7 +104,7 @@ public class ClusterWideStorageProfileValidator implements 
StorageProfileValidat
     }
 
     private static Set<String> 
extractStorageProfileNamesFromLogicalTopologySnapshot(LogicalTopologySnapshot 
snapshot) {
-        Set<LogicalNode> logicalNodes = snapshot.nodes();
+        Collection<LogicalNode> logicalNodes = snapshot.nodes();
 
         // Assume default persistent + rocks + aimem profiles on each node in 
average.
         Set<String> topologyWideProfiles = new HashSet<>(logicalNodes.size() * 
3);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
index 8a79b01d84c..8693e257d27 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
@@ -29,7 +29,6 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -55,7 +54,7 @@ public class StatisticAggregatorImpl implements
         StatisticAggregator<Collection<InternalTable>, 
CompletableFuture<Int2ObjectMap<PartitionModificationInfo>>> {
     private static final IgniteLogger LOG = 
Loggers.forClass(StatisticAggregatorImpl.class);
 
-    private final Supplier<Set<LogicalNode>> clusterNodes;
+    private final Supplier<Collection<LogicalNode>> clusterNodes;
 
     private final MessagingService messagingService;
 
@@ -68,7 +67,7 @@ public class StatisticAggregatorImpl implements
 
     /** Constructor. */
     public StatisticAggregatorImpl(
-            Supplier<Set<LogicalNode>> clusterNodes,
+            Supplier<Collection<LogicalNode>> clusterNodes,
             MessagingService messagingService
     ) {
         this.clusterNodes = clusterNodes;
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
index d989ce29c7c..3db3d33b4f4 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
@@ -148,10 +148,7 @@ public class ClusterServiceFactory {
         }
 
         private static @Nullable InternalClusterNode 
findNodeByName(LogicalTopology logicalTopology, String name) {
-            return logicalTopology.getLogicalTopology().nodes().stream()
-                    .filter(node -> node.name().equals(name))
-                    .findFirst()
-                    .orElse(null);
+            return 
logicalTopology.getLogicalTopology().node(name).orElse(null);
         }
 
         @Override
@@ -195,10 +192,7 @@ public class ClusterServiceFactory {
 
         @Override
         public @Nullable InternalClusterNode getById(UUID id) {
-            return logicalTopology.getLogicalTopology().nodes().stream()
-                    .filter(node -> node.id().equals(id))
-                    .findFirst()
-                    .orElse(null);
+            return logicalTopology.getLogicalTopology().node(id).orElse(null);
         }
 
         @Override
diff --git 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
index 87f6029a643..c2dd9a90e43 100644
--- 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
+++ 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
@@ -124,8 +124,7 @@ class ItCmgDisasterRecoveryTest extends 
ItSystemGroupDisasterRecoveryTest {
         IgniteImpl node2 = unwrapIgniteImpl(cluster.startNode(2));
 
         assertTrue(waitForCondition(
-                () -> 
node2.logicalTopologyService().localLogicalTopology().nodes().stream()
-                        .anyMatch(n -> node2.name().equals(n.name())),
+                () -> 
node2.logicalTopologyService().localLogicalTopology().hasNode(node2.name()),
                 SECONDS.toMillis(10)
         ));
     }
diff --git 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
index ed5ed9368c2..a9e14d215c4 100644
--- 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
+++ 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
@@ -138,6 +138,6 @@ abstract class ItSystemGroupDisasterRecoveryTest extends 
ClusterPerTestIntegrati
     }
 
     final void assertTopologyContainsNode(int nodeIndex, 
LogicalTopologySnapshot topologySnapshot) {
-        assertTrue(topologySnapshot.nodes().stream().anyMatch(node -> 
node.name().equals(cluster.nodeName(nodeIndex))));
+        assertTrue(topologySnapshot.hasNode(cluster.nodeName(nodeIndex)));
     }
 }
diff --git 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
index 7af3be4746a..37285d0049a 100644
--- 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
+++ 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
@@ -556,10 +556,7 @@ public class 
ItHighAvailablePartitionsRecoveryByFilterUpdateTest extends Abstrac
     }
 
     private static LogicalNode getLogicalNode(IgniteImpl ignite) {
-
-        return 
ignite.logicalTopologyService().localLogicalTopology().nodes().stream()
-                .filter(n -> n.name().equals(ignite.name()))
-                .findFirst()
+        return 
ignite.logicalTopologyService().localLogicalTopology().node(ignite.name())
                 .orElseThrow(() -> new IllegalStateException("Node not found 
in logical topology: " + ignite.name()));
     }
 }

Reply via email to