将键值对流的键值对对象从内部类调整为AbstractMap.SimpleImmutableEntry

This commit is contained in:
huangchengxing 2022-09-02 16:14:47 +08:00
parent 43bd15b515
commit 3c5313f0a7
2 changed files with 89 additions and 105 deletions

View File

@ -1,6 +1,7 @@
package cn.hutool.core.stream; package cn.hutool.core.stream;
import cn.hutool.core.collection.ConcurrentHashSet; import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.collection.iter.IterUtil;
import cn.hutool.core.map.multi.RowKeyTable; import cn.hutool.core.map.multi.RowKeyTable;
import cn.hutool.core.map.multi.Table; import cn.hutool.core.map.multi.Table;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
@ -13,9 +14,9 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
/** /**
* <p>针对键值对对象{@link Map.Entry}特化的增强流 * <p>参考StreamEx的EntryStream与vavr的Map针对键值对对象{@link Map.Entry}特化的增强流实现<br>
* 本身可视为一个元素类型为{@link Map.Entry}{@link Stream}<br> * 本身可视为一个元素类型为{@link Map.Entry}{@link Stream}
* 用于支持流式处理{@link Map}集合中的具有潜在可能转为{@link Map}集合的数据 * 用于支持流式处理{@link Map}集合中的其他键值对类型的数据
* *
* @param <K> 键类型 * @param <K> 键类型
* @param <V> 值类型 * @param <V> 值类型
@ -23,6 +24,11 @@ import java.util.stream.StreamSupport;
*/ */
public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStream<K, V>> { public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStream<K, V>> {
/**
* 默认的空键值对
*/
private static final Map.Entry<?, ?> EMPTY_ENTRY = new AbstractMap.SimpleImmutableEntry<>(null, null);
/** /**
* 根据键与值的集合创建键值对流若两集合在相同下标的位置找不到对应的键或值则使用{@code null}填充<br> * 根据键与值的集合创建键值对流若两集合在相同下标的位置找不到对应的键或值则使用{@code null}填充<br>
* 比如: {@code [1, 2, 3]}{@code [1, 2]}合并则得到{@code [{1=1}, {2=2}, {3=null}]} * 比如: {@code [1, 2, 3]}{@code [1, 2]}合并则得到{@code [{1=1}, {2=2}, {3=null}]}
@ -51,7 +57,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
final Iterator<A> keyItr = keys.iterator(); final Iterator<A> keyItr = keys.iterator();
final Iterator<B> valueItr = values.iterator(); final Iterator<B> valueItr = values.iterator();
while (keyItr.hasNext() || valueItr.hasNext()) { while (keyItr.hasNext() || valueItr.hasNext()) {
entries.add(new Entry<>( entries.add(ofEntry(
keyItr.hasNext() ? keyItr.next() : null, keyItr.hasNext() ? keyItr.next() : null,
valueItr.hasNext() ? valueItr.next() : null valueItr.hasNext() ? valueItr.next() : null
)); ));
@ -106,7 +112,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
return empty(); return empty();
} }
final Stream<Map.Entry<A, B>> stream = StreamSupport.stream(source.spliterator(), false) final Stream<Map.Entry<A, B>> stream = StreamSupport.stream(source.spliterator(), false)
.map(t -> new Entry<>(keyMapper.apply(t), valueMapper.apply(t))); .map(t -> ofEntry(keyMapper.apply(t), valueMapper.apply(t)));
return new EntryStream<>(stream); return new EntryStream<>(stream);
} }
@ -121,7 +127,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
*/ */
public static <A, B> EntryStream<A, B> of(Stream<? extends Map.Entry<A, B>> stream) { public static <A, B> EntryStream<A, B> of(Stream<? extends Map.Entry<A, B>> stream) {
return ObjUtil.isNull(stream) ? return ObjUtil.isNull(stream) ?
empty() : new EntryStream<>(stream.map(Entry::new)); empty() : new EntryStream<>(stream.map(EntryStream::ofEntry));
} }
/** /**
@ -142,19 +148,6 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
super(stream); super(stream);
} }
// ================================ override ================================
/**
* 根据一个原始的流返回一个新包装类实例
*
* @param stream
* @return 实现类
*/
@Override
protected EntryStream<K, V> convertToStreamImpl(Stream<Map.Entry<K, V>> stream) {
return new EntryStream<>(stream);
}
// ================================ 中间操作 ================================ // ================================ 中间操作 ================================
/** /**
@ -164,7 +157,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
*/ */
public EntryStream<K, V> distinctByKey() { public EntryStream<K, V> distinctByKey() {
Set<K> accessed = new ConcurrentHashSet<>(16); Set<K> accessed = new ConcurrentHashSet<>(16);
return new EntryStream<>(stream.filter(e -> { return convertToStreamImpl(stream.filter(e -> {
K key = e.getKey(); K key = e.getKey();
if (accessed.contains(key)) { if (accessed.contains(key)) {
return false; return false;
@ -181,7 +174,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
*/ */
public EntryStream<K, V> distinctByValue() { public EntryStream<K, V> distinctByValue() {
Set<V> accessed = new ConcurrentHashSet<>(16); Set<V> accessed = new ConcurrentHashSet<>(16);
return new EntryStream<>(stream.filter(e -> { return convertToStreamImpl(stream.filter(e -> {
V val = e.getValue(); V val = e.getValue();
if (accessed.contains(val)) { if (accessed.contains(val)) {
return false; return false;
@ -229,6 +222,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
* *
* @return {@link EntryStream}实例 * @return {@link EntryStream}实例
*/ */
@Override
public EntryStream<K, V> nonNull() { public EntryStream<K, V> nonNull() {
return super.filter(e -> ObjUtil.isNotNull(e) && ObjUtil.isNotNull(e.getKey()) && ObjUtil.isNotNull(e.getValue())); return super.filter(e -> ObjUtil.isNotNull(e) && ObjUtil.isNotNull(e.getKey()) && ObjUtil.isNotNull(e.getValue()));
} }
@ -304,8 +298,49 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
* @param value * @param value
* @return {@link EntryStream}实例 * @return {@link EntryStream}实例
*/ */
public EntryStream<K, V> push(K key, V value) { public EntryStream<K, V> append(K key, V value) {
return new EntryStream<>(Stream.concat(stream, Stream.of(new Entry<>(key, value)))); return convertToStreamImpl(Stream.concat(stream, Stream.of(ofEntry(key, value))));
}
/**
* 项当前流队首追加元素
*
* @param key
* @param value
* @return {@link EntryStream}实例
*/
public EntryStream<K, V> prepend(K key, V value) {
return convertToStreamImpl(Stream.concat(Stream.of(ofEntry(key, value)), stream));
}
/**
* 将输入元素转为流返回一个前半段为当前流后半段为新流的新{@link EasyStream}实例
*
* @param entries 键值对
* @return {@link EntryStream}实例
*/
public EntryStream<K, V> append(Iterable<? extends Map.Entry<K, V>> entries) {
if (IterUtil.isEmpty(entries)) {
return this;
}
final Stream<Map.Entry<K, V>> contacted = StreamSupport.stream(entries.spliterator(), isParallel())
.map(EntryStream::ofEntry);
return convertToStreamImpl(Stream.concat(stream, contacted));
}
/**
* 将输入元素转为流返回一个前半段为新流后半段为当前流的新{@link EasyStream}实例
*
* @param entries 键值对
* @return {@link EntryStream}实例
*/
public EntryStream<K, V> prepend(Iterable<? extends Map.Entry<K, V>> entries) {
if (IterUtil.isEmpty(entries)) {
return this;
}
final Stream<Map.Entry<K, V>> contacted = StreamSupport.stream(entries.spliterator(), isParallel())
.map(EntryStream::ofEntry);
return convertToStreamImpl(Stream.concat(contacted, stream));
} }
/** /**
@ -336,7 +371,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
public <N> EntryStream<N, V> mapKeys(Function<? super K, ? extends N> mapper) { public <N> EntryStream<N, V> mapKeys(Function<? super K, ? extends N> mapper) {
Objects.requireNonNull(mapper); Objects.requireNonNull(mapper);
return new EntryStream<>( return new EntryStream<>(
stream.map(e -> new Entry<>(mapper.apply(e.getKey()), e.getValue())) stream.map(e -> ofEntry(mapper.apply(e.getKey()), e.getValue()))
); );
} }
@ -350,7 +385,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
public <N> EntryStream<K, N> mapValues(Function<? super V, ? extends N> mapper) { public <N> EntryStream<K, N> mapValues(Function<? super V, ? extends N> mapper) {
Objects.requireNonNull(mapper); Objects.requireNonNull(mapper);
return new EntryStream<>( return new EntryStream<>(
stream.map(e -> new Entry<>(e.getKey(), mapper.apply(e.getValue()))) stream.map(e -> ofEntry(e.getKey(), mapper.apply(e.getValue())))
); );
} }
@ -417,7 +452,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
return new EntryStream<>( return new EntryStream<>(
stream.flatMap(e -> keyMapper stream.flatMap(e -> keyMapper
.apply(e.getKey()) .apply(e.getKey())
.map(newKey -> new Entry<>(newKey, e.getValue())) .map(newKey -> ofEntry(newKey, e.getValue()))
) )
); );
} }
@ -441,7 +476,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
return new EntryStream<>( return new EntryStream<>(
stream.flatMap(e -> valueMapper stream.flatMap(e -> valueMapper
.apply(e.getValue()) .apply(e.getValue())
.map(newVal -> new Entry<>(e.getKey(), newVal)) .map(newVal -> ofEntry(e.getKey(), newVal))
) )
); );
} }
@ -625,7 +660,7 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
*/ */
public EntryStream<V, K> inverse() { public EntryStream<V, K> inverse() {
return new EntryStream<>( return new EntryStream<>(
stream.map(e -> new Entry<>(e.getValue(), e.getKey())) stream.map(e -> ofEntry(e.getValue(), e.getKey()))
); );
} }
@ -683,85 +718,34 @@ public class EntryStream<K, V> extends StreamWrapper<Map.Entry<K, V>, EntryStrea
return super.noneMatch(e -> predicate.test(e.getKey(), e.getValue())); return super.noneMatch(e -> predicate.test(e.getKey(), e.getValue()));
} }
/** // ========================= private =========================
* {@link Map.Entry}的基本实现
*/
static class Entry<K, V> implements Map.Entry<K, V> {
/** /**
* * 将键值对转为{@link AbstractMap.SimpleImmutableEntry}
*/ */
private final K key; @SuppressWarnings("unchecked")
private static <K, V> Map.Entry<K, V> ofEntry(Map.Entry<K, V> entry) {
/** return ObjUtil.defaultIfNull(
* entry, e -> ofEntry(e.getKey(), e.getValue()), (Map.Entry<K, V>)EMPTY_ENTRY
*/ );
private V val;
/**
* 创建一个简单键值对对象
*
* @param key
* @param val
*/
public Entry(K key, V val) {
this.key = key;
this.val = val;
} }
/** /**
* 创建一个简单键值对对象 * 将键值对转为{@link AbstractMap.SimpleImmutableEntry}
*
* @param entry 键值对
*/ */
public Entry(Map.Entry<K, V> entry) { private static <K, V> Map.Entry<K, V> ofEntry(K key, V value) {
if (ObjUtil.isNull(entry)) { return new AbstractMap.SimpleImmutableEntry<>(key, value);
this.key = null;
this.val = null;
} else {
this.key = entry.getKey();
this.val = entry.getValue();
}
} }
/** /**
* 获取键 * 根据一个原始的流返回一个新包装类实例
* *
* @return * @param stream
* @return 实现类
*/ */
@Override @Override
public K getKey() { public EntryStream<K, V> convertToStreamImpl(Stream<Map.Entry<K, V>> stream) {
return key; return new EntryStream<>(stream);
}
/**
* 获取值
*
* @return
*/
@Override
public V getValue() {
return val;
}
/**
* 设置值
*
* @param value
* @return 旧值
*/
@Override
public V setValue(V value) {
V old = val;
val = value;
return old;
}
@Override
public String toString() {
return "{" + key + "=" + val + '}';
}
} }
/** /**

View File

@ -116,8 +116,8 @@ public class EntryStreamTest {
Assert.assertEquals( Assert.assertEquals(
5, 5,
EntryStream.of(Arrays.asList(1, 2, 3), Function.identity(), Function.identity()) EntryStream.of(Arrays.asList(1, 2, 3), Function.identity(), Function.identity())
.push(4, 4) .append(4, 4)
.push(5, 5) .append(5, 5)
.count() .count()
); );