Skip to content

Commit 20a5694

Browse files
lowasserGoogle Java Core Libraries
authored andcommitted
Propagate more detailed spliterator characteristics throughout collect.
Fixes #8088 RELNOTES=n/a PiperOrigin-RevId: 833504486
1 parent a6110d3 commit 20a5694

24 files changed

+160
-32
lines changed

guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.util.List;
3333
import java.util.Map;
3434
import java.util.Map.Entry;
35-
import java.util.Spliterator;
3635
import java.util.function.BinaryOperator;
3736
import java.util.function.Function;
3837
import java.util.stream.Collector;
@@ -477,10 +476,6 @@ public K next() {
477476
};
478477
}
479478

480-
Spliterator<K> keySpliterator() {
481-
return CollectSpliterators.map(entrySet().spliterator(), Entry::getKey);
482-
}
483-
484479
private transient @Nullable ImmutableCollection<V> cachedValues = null;
485480

486481
@Override

guava-tests/test/com/google/common/collect/CollectSpliteratorsTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static com.google.common.truth.Truth.assertThat;
1919

2020
import com.google.common.annotations.GwtCompatible;
21+
import com.google.common.annotations.GwtIncompatible;
2122
import com.google.common.base.Ascii;
2223
import com.google.common.collect.testing.SpliteratorTester;
2324
import java.util.ArrayList;
@@ -34,11 +35,14 @@
3435
@GwtCompatible
3536
@NullMarked
3637
public class CollectSpliteratorsTest extends TestCase {
38+
@GwtIncompatible
3739
public void testMap() {
3840
SpliteratorTester.of(
3941
() ->
4042
CollectSpliterators.map(
41-
Arrays.spliterator(new String[] {"a", "b", "c", "d", "e"}), Ascii::toUpperCase))
43+
Arrays.spliterator(new String[] {"a", "b", "c", "d", "e"}),
44+
0,
45+
Ascii::toUpperCase))
4246
.expect("A", "B", "C", "D", "E");
4347
}
4448

guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@
3434
import com.google.common.collect.testing.TestEnumMapGenerator;
3535
import com.google.common.collect.testing.features.CollectionSize;
3636
import com.google.common.testing.CollectorTester;
37+
import com.google.common.truth.Truth;
3738
import java.util.HashMap;
3839
import java.util.Map;
3940
import java.util.Map.Entry;
41+
import java.util.Spliterator;
4042
import java.util.stream.Collector;
4143
import java.util.stream.Stream;
4244
import junit.framework.Test;
@@ -145,4 +147,31 @@ public void testToImmutableMapMerging() {
145147
mapEntry(AnEnum.C, 3),
146148
mapEntry(AnEnum.B, 2));
147149
}
150+
151+
@GwtIncompatible
152+
@J2ktIncompatible
153+
public void testEntrySetSpliteratorCharacteristics() {
154+
int expectedCharacteristics =
155+
Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE;
156+
Spliterator<Entry<AnEnum, String>> spliterator =
157+
Maps.immutableEnumMap(ImmutableMap.of(AnEnum.A, "a", AnEnum.B, "b"))
158+
.entrySet()
159+
.spliterator();
160+
Truth.assertWithMessage(spliterator.getClass().toString())
161+
.that(spliterator.characteristics() & expectedCharacteristics)
162+
.isEqualTo(expectedCharacteristics);
163+
}
164+
165+
@GwtIncompatible
166+
@J2ktIncompatible
167+
public void testKeySetCharacteristics() {
168+
int expectedCharacteristics = Spliterator.ORDERED | Spliterator.NONNULL;
169+
assertThat(
170+
Maps.immutableEnumMap(ImmutableMap.of(AnEnum.A, "a"))
171+
.keySet()
172+
.spliterator()
173+
.characteristics()
174+
& expectedCharacteristics)
175+
.isEqualTo(expectedCharacteristics);
176+
}
148177
}

guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.Collection;
4646
import java.util.Collections;
4747
import java.util.Map.Entry;
48+
import java.util.Spliterator;
4849
import java.util.function.BiPredicate;
4950
import java.util.stream.Collector;
5051
import junit.framework.Test;
@@ -572,6 +573,13 @@ public void testInverse() {
572573
ImmutableListMultimap.of("foo", 'f', "foo", 'o', "foo", 'o').inverse());
573574
}
574575

576+
public void testNotDistinctEntrySpliterator() {
577+
ImmutableListMultimap<String, String> multimap =
578+
ImmutableListMultimap.of("foo", "bar", "foo", "bar");
579+
assertThat(multimap.entries().spliterator().characteristics() & Spliterator.DISTINCT)
580+
.isEqualTo(0);
581+
}
582+
575583
public void testInverseMinimizesWork() {
576584
ImmutableListMultimap<String, Character> multimap =
577585
ImmutableListMultimap.<String, Character>builder()

guava-tests/test/com/google/common/collect/ImmutableMapTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import java.util.Map;
6565
import java.util.Map.Entry;
6666
import java.util.Set;
67+
import java.util.Spliterator;
6768
import java.util.regex.Matcher;
6869
import java.util.regex.Pattern;
6970
import java.util.stream.Collector;
@@ -1169,4 +1170,11 @@ public void testBuilderPutAllEntryListJdkBacked() {
11691170
entryList.get(0).setValue("3");
11701171
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
11711172
}
1173+
1174+
@GwtIncompatible
1175+
public void testEntrySetSpliteratorDistinct() {
1176+
ImmutableMap<String, String> map = ImmutableMap.of("foo", "bar", "baz", "quux");
1177+
assertThat(map.entrySet().spliterator().characteristics() & Spliterator.DISTINCT)
1178+
.isNotEqualTo(0);
1179+
}
11721180
}

guava/src/com/google/common/collect/AbstractMapBasedMultimap.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,9 @@ Spliterator<Entry<K, V>> entrySpliterator() {
12981298
K key = keyToValueCollectionEntry.getKey();
12991299
Collection<V> valueCollection = keyToValueCollectionEntry.getValue();
13001300
return CollectSpliterators.map(
1301-
valueCollection.spliterator(), (V value) -> immutableEntry(key, value));
1301+
valueCollection.spliterator(),
1302+
Spliterator.DISTINCT | Spliterator.NONNULL,
1303+
(V value) -> immutableEntry(key, value));
13021304
},
13031305
Spliterator.SIZED,
13041306
size());
@@ -1428,7 +1430,10 @@ public Iterator<Entry<K, Collection<V>>> iterator() {
14281430

14291431
@Override
14301432
public Spliterator<Entry<K, Collection<V>>> spliterator() {
1431-
return CollectSpliterators.map(submap.entrySet().spliterator(), AsMap.this::wrapEntry);
1433+
return CollectSpliterators.map(
1434+
submap.entrySet().spliterator(),
1435+
Spliterator.DISTINCT | Spliterator.NONNULL,
1436+
AsMap.this::wrapEntry);
14321437
}
14331438

14341439
// The following methods are included for performance.

guava/src/com/google/common/collect/AbstractTable.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static com.google.common.collect.Maps.safeGet;
1919

2020
import com.google.common.annotations.GwtCompatible;
21+
import com.google.common.annotations.GwtIncompatible;
2122
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2223
import com.google.errorprone.annotations.concurrent.LazyInit;
2324
import com.google.j2objc.annotations.WeakOuter;
@@ -28,6 +29,7 @@
2829
import java.util.Map;
2930
import java.util.Set;
3031
import java.util.Spliterator;
32+
import java.util.Spliterators;
3133
import org.jspecify.annotations.Nullable;
3234

3335
/**
@@ -127,7 +129,9 @@ Set<Cell<R, C, V>> createCellSet() {
127129

128130
abstract Iterator<Table.Cell<R, C, V>> cellIterator();
129131

130-
abstract Spliterator<Table.Cell<R, C, V>> cellSpliterator();
132+
Spliterator<Table.Cell<R, C, V>> cellSpliterator() {
133+
return Spliterators.spliterator(cellSet(), Spliterator.NONNULL | Spliterator.DISTINCT);
134+
}
131135

132136
@WeakOuter
133137
private final class CellSet extends AbstractSet<Cell<R, C, V>> {
@@ -198,8 +202,9 @@ V transform(Cell<R, C, V> cell) {
198202
};
199203
}
200204

205+
@GwtIncompatible("Spliterator")
201206
Spliterator<V> valuesSpliterator() {
202-
return CollectSpliterators.map(cellSpliterator(), Table.Cell::getValue);
207+
return CollectSpliterators.map(cellSpliterator(), 0, Table.Cell::getValue);
203208
}
204209

205210
@WeakOuter
@@ -210,6 +215,7 @@ public Iterator<V> iterator() {
210215
}
211216

212217
@Override
218+
@GwtIncompatible("Spliterator")
213219
public Spliterator<V> spliterator() {
214220
return valuesSpliterator();
215221
}

guava/src/com/google/common/collect/ArrayTable.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,10 @@ protected Entry<K, V> get(int index) {
256256
}
257257

258258
@Override
259+
@GwtIncompatible("Spliterator")
259260
Spliterator<Entry<K, V>> entrySpliterator() {
260-
return CollectSpliterators.indexed(size(), Spliterator.ORDERED, this::getEntry);
261+
return CollectSpliterators.indexed(
262+
size(), Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.NONNULL, this::getEntry);
261263
}
262264

263265
// TODO(lowasser): consider an optimized values() implementation
@@ -801,6 +803,7 @@ String getKeyRole() {
801803
}
802804

803805
@Override
806+
@GwtIncompatible("Spliterator")
804807
Spliterator<@Nullable V> valuesSpliterator() {
805808
return CollectSpliterators.<@Nullable V>indexed(size(), Spliterator.ORDERED, this::getValue);
806809
}

guava/src/com/google/common/collect/CollectSpliterators.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public int characteristics() {
108108
static <InElementT extends @Nullable Object, OutElementT extends @Nullable Object>
109109
Spliterator<OutElementT> map(
110110
Spliterator<InElementT> fromSpliterator,
111+
int characteristics,
111112
Function<? super InElementT, ? extends OutElementT> function) {
112113
checkNotNull(fromSpliterator);
113114
checkNotNull(function);
@@ -127,7 +128,7 @@ public void forEachRemaining(Consumer<? super OutElementT> action) {
127128
@Override
128129
public @Nullable Spliterator<OutElementT> trySplit() {
129130
Spliterator<InElementT> fromSplit = fromSpliterator.trySplit();
130-
return (fromSplit != null) ? map(fromSplit, function) : null;
131+
return (fromSplit != null) ? map(fromSplit, characteristics, function) : null;
131132
}
132133

133134
@Override
@@ -137,8 +138,15 @@ public long estimateSize() {
137138

138139
@Override
139140
public int characteristics() {
140-
return fromSpliterator.characteristics()
141-
& ~(Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.SORTED);
141+
int backingCharacteristics = fromSpliterator.characteristics();
142+
// the following are inherently inherited:
143+
backingCharacteristics &=
144+
Spliterator.SIZED
145+
| Spliterator.SUBSIZED
146+
| Spliterator.ORDERED
147+
| Spliterator.IMMUTABLE
148+
| Spliterator.CONCURRENT;
149+
return characteristics | backingCharacteristics;
142150
}
143151
};
144152
}

guava/src/com/google/common/collect/Collections2.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static java.util.Objects.requireNonNull;
2424

2525
import com.google.common.annotations.GwtCompatible;
26+
import com.google.common.annotations.GwtIncompatible;
2627
import com.google.common.base.Function;
2728
import com.google.common.base.Predicate;
2829
import com.google.common.base.Predicates;
@@ -177,6 +178,7 @@ public Iterator<E> iterator() {
177178
}
178179

179180
@Override
181+
@GwtIncompatible("Spliterator")
180182
public Spliterator<E> spliterator() {
181183
return CollectSpliterators.filter(unfiltered.spliterator(), predicate);
182184
}
@@ -288,8 +290,9 @@ public Iterator<T> iterator() {
288290
}
289291

290292
@Override
293+
@GwtIncompatible("Spliterator")
291294
public Spliterator<T> spliterator() {
292-
return CollectSpliterators.map(fromCollection.spliterator(), function);
295+
return CollectSpliterators.map(fromCollection.spliterator(), 0, function);
293296
}
294297

295298
@Override

0 commit comments

Comments
 (0)