Skip to content

KAFKA-20297: Cleanup org.apache.kafka.common.utils.CollectionUtils#21818

Merged
chia7712 merged 11 commits intoapache:trunkfrom
unknowntpo:cleanup-common-utils-20297
Mar 30, 2026
Merged

KAFKA-20297: Cleanup org.apache.kafka.common.utils.CollectionUtils#21818
chia7712 merged 11 commits intoapache:trunkfrom
unknowntpo:cleanup-common-utils-20297

Conversation

@unknowntpo
Copy link
Copy Markdown
Contributor

@unknowntpo unknowntpo commented Mar 19, 2026

This PR removes CollectionUtils entirely (KAFKA-20297) by replacing
all usages with alternatives.

Reviewers: Chia-Ping Tsai chia7712@gmail.com

@github-actions github-actions bot added triage PRs from the community consumer clients labels Mar 19, 2026
@chia7712
Copy link
Copy Markdown
Member

@unknowntpo would you mind rebasing code?

@unknowntpo unknowntpo force-pushed the cleanup-common-utils-20297 branch from 7e2ef79 to 10b13ba Compare March 21, 2026 00:30
@unknowntpo
Copy link
Copy Markdown
Contributor Author

unknowntpo commented Mar 21, 2026

@unknowntpo would you mind rebasing code?

Ok, rebased.

@github-actions github-actions bot added the core Kafka Broker label Mar 21, 2026
@unknowntpo unknowntpo force-pushed the cleanup-common-utils-20297 branch from 82b9572 to 4aea5f0 Compare March 21, 2026 05:07
@unknowntpo
Copy link
Copy Markdown
Contributor Author

and ci errors are fixed.

return new MemberData(partitions, generation);
}

private static Map<String, List<Integer>> groupPartitionsByTopic(Collection<TopicPartition> partitions) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you inline it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -90,6 +89,12 @@ public Map<String, String> ignoredExtensions() {
return Collections.unmodifiableMap(subtractMap(subtractMap(inputExtensions.map(), invalidExtensions), validatedExtensions));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original logic will create map repeatedly. Could you use for-loop to streamline it?

public Map<String, String> ignoredExtensions() {
    Map<String, String> ignored = new HashMap<>();
    for (Map.Entry<String, String> entry : inputExtensions.map().entrySet()) {
        String key = entry.getKey();
        if (!invalidExtensions.containsKey(key) && !validatedExtensions.containsKey(key)) {
            ignored.put(key, entry.getValue());
        }
    }
    return Collections.unmodifiableMap(ignored);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the subtractMap is more Functional Programming style, more declarative, and this path is unlikely a hot path, which is not suitable for repeating memory allocation, but your approach is okay for me, I'll change it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

return new DescribeProducersResponse(response);
}

private static Map<String, Map<Integer, PartitionResponse>> groupPartitionDataByTopic(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use such complex structure in tests actually. Maybe we could use describeProducersResponse(TopicPartition partition, PartitionResponse partitionResponse) instead

Copy link
Copy Markdown
Contributor Author

@unknowntpo unknowntpo Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, since caller only pass single TopicPartition and PartitionResponse, so the Map input was unnecessary.


Map<String, List<Integer>> map = CollectionUtils.groupPartitionsByTopic(partitions);
Map<String, List<Integer>> otherMap = CollectionUtils.groupPartitionsByTopic(otherPartitions);
Map<String, List<Integer>> map = groupPartitionsByTopic(partitions);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could streamline the test.

Set<String> otherTopics = otherPartitions.stream()
    .map(TopicPartition::topic)
    .collect(Collectors.toSet());

for (TopicPartition tp : partitions) {
    assertFalse(otherTopics.contains(tp.topic()), 
        "Error: Some partitions can be moved...");
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, done, this is simple because we only use the topic name, lesson learned.

@github-actions github-actions bot removed the triage PRs from the community label Mar 22, 2026
…from CollectionUtils

Replace all callers with idiomatic alternatives:
- DescribeProducersHandler: add mapKey:true to DescribeProducersRequest.json and use find() on TopicRequestCollection
- ListOffsetsHandler: use HashMap+computeIfAbsent

Also fix Scala test callers affected by the DescribeProducersRequest mapKey change.
Inline subtractMap as a private helper in OAuthBearerExtensionsValidatorCallback,
then delete the now-empty CollectionUtils class and its test.
…ethod

Extract repeated stream-based grouping logic into a private groupPartitionsByTopic
helper in StickyAssignor and AbstractStickyAssignorTest.
@unknowntpo unknowntpo force-pushed the cleanup-common-utils-20297 branch from 05ad35d to ceb7923 Compare March 26, 2026 00:14
Copy link
Copy Markdown
Member

@chia7712 chia7712 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@unknowntpo thanks for this update

Struct struct = new Struct(STICKY_ASSIGNOR_USER_DATA_V1);
List<Struct> topicAssignments = new ArrayList<>();
for (Map.Entry<String, List<Integer>> topicEntry : CollectionUtils.groupPartitionsByTopic(memberData.partitions).entrySet()) {
Map<String, List<Integer>> partitionsByTopic = memberData.partitions.stream()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about the performance. Would you mind using for loop instead?

        var partitionsByTopic = new HashMap<String, List<Integer>>();
        for (TopicPartition tp : memberData.partitions) {
            partitionsByTopic.computeIfAbsent(tp.topic(), t -> new ArrayList<>()).add(tp.partition());
        }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok fixed.

@chia7712 chia7712 merged commit a1c155e into apache:trunk Mar 30, 2026
24 checks passed
@unknowntpo unknowntpo deleted the cleanup-common-utils-20297 branch March 30, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants