add MapJoiner

This commit is contained in:
Looly 2022-10-22 19:58:25 +08:00
parent d748366dfe
commit df108a2dd7
6 changed files with 181 additions and 27 deletions

View File

@ -183,7 +183,7 @@ public class IterUtil {
/**
* 获取指定Bean列表中某个字段生成新的列表
*
* @param <R> 返回元素类型
* @param <R> 返回元素类型
* @param <V> 对象类型
* @param iterable 对象列表
* @param fieldName 字段名会通过反射获取其值
@ -197,7 +197,7 @@ public class IterUtil {
/**
* 获取指定Bean列表中某个字段生成新的列表
*
* @param <R> 返回元素类型
* @param <R> 返回元素类型
* @param <V> 对象类型
* @param iter 对象列表
* @param fieldName 字段名会通过反射获取其值
@ -211,7 +211,7 @@ public class IterUtil {
V value;
while (iter.hasNext()) {
value = iter.next();
result.add((R)FieldUtil.getFieldValue(value, fieldName));
result.add((R) FieldUtil.getFieldValue(value, fieldName));
}
}
return result;
@ -460,6 +460,7 @@ public class IterUtil {
* @param index 位置
* @param <E> 元素类型
* @return 元素找不到元素返回{@code null}
* @throws IndexOutOfBoundsException index < 0时报错
* @since 5.8.0
*/
public static <E> E get(final Iterator<E> iterator, int index) throws IndexOutOfBoundsException {

View File

@ -0,0 +1,109 @@
package cn.hutool.core.map;
import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Predicate;
/**
* Map拼接器可以拼接包括MapEntry列表等
*
* @author looly
*/
public class MapJoiner {
private final StrJoiner joiner;
private final String keyValueSeparator;
/**
* 构建一个MapJoiner
*
* @param separator entry之间的连接符
* @param keyValueSeparator kv之间的连接符
* @return MapJoiner
*/
public static MapJoiner of(final String separator, final String keyValueSeparator) {
return of(StrJoiner.of(separator), keyValueSeparator);
}
/**
* 构建一个MapJoiner
*
* @param joiner entry之间的Joiner
* @param keyValueSeparator kv之间的连接符
* @return MapJoiner
*/
public static MapJoiner of(final StrJoiner joiner, final String keyValueSeparator) {
return new MapJoiner(joiner, keyValueSeparator);
}
/**
* 构造
*
* @param joiner entry之间的Joiner
* @param keyValueSeparator kv之间的连接符
*/
public MapJoiner(final StrJoiner joiner, final String keyValueSeparator) {
this.joiner = joiner;
this.keyValueSeparator = keyValueSeparator;
}
/**
* 追加Map
*
* @param <K> 键类型
* @param <V> 值类型
* @param map Map
* @param predicate Map过滤器
* @return this
*/
public <K, V> MapJoiner append(final Map<K, V> map, final Predicate<Map.Entry<K, V>> predicate) {
return append(map.entrySet().iterator(), predicate);
}
/**
* 追加Entry列表
*
* @param <K> 键类型
* @param <V> 值类型
* @param parts Entry列表
* @param predicate Map过滤器
* @return this
*/
public <K, V> MapJoiner append(final Iterator<? extends Map.Entry<K, V>> parts, final Predicate<Map.Entry<K, V>> predicate) {
if (null == parts) {
return this;
}
Map.Entry<K, V> entry;
while (parts.hasNext()) {
entry = parts.next();
if (null == predicate || predicate.test(entry)) {
joiner.append(StrJoiner.of(this.keyValueSeparator).append(entry.getKey()).append(entry.getValue()));
}
}
return this;
}
/**
* 追加其他字符串其他字符串简单拼接
*
* @param params 字符串列表
* @return this
*/
public MapJoiner append(final String... params) {
if(ArrayUtil.isNotEmpty(params)){
joiner.append(StrUtil.concat(false, params));
}
return this;
}
@Override
public String toString() {
return joiner.toString();
}
}

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.collection.iter.ArrayIter;
import cn.hutool.core.collection.iter.IterUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.text.StrUtil;
@ -605,28 +604,30 @@ public class MapUtil extends MapGetUtil {
* @return 连接后的字符串map和otherParams为空返回""
* @since 3.1.1
*/
public static <K, V> String join(final Map<K, V> map, final String separator, final String keyValueSeparator, final boolean isIgnoreNull, final String... otherParams) {
final StringBuilder strBuilder = StrUtil.builder();
boolean isFirst = true;
if (isNotEmpty(map)) {
for (final Entry<K, V> entry : map.entrySet()) {
if (false == isIgnoreNull || entry.getKey() != null && entry.getValue() != null) {
if (isFirst) {
isFirst = false;
} else {
strBuilder.append(separator);
}
strBuilder.append(Convert.toStr(entry.getKey())).append(keyValueSeparator).append(Convert.toStr(entry.getValue()));
}
}
}
// 补充其它字符串到末尾默认无分隔符
if (ArrayUtil.isNotEmpty(otherParams)) {
for (final String otherParam : otherParams) {
strBuilder.append(otherParam);
}
}
return strBuilder.toString();
public static <K, V> String join(final Map<K, V> map, final String separator, final String keyValueSeparator,
final boolean isIgnoreNull, final String... otherParams) {
return join(map, separator, keyValueSeparator, (entry) -> false == isIgnoreNull || entry.getKey() != null && entry.getValue() != null, otherParams);
}
/**
* 将map转成字符串
*
* @param <K> 键类型
* @param <V> 值类型
* @param map Map为空返回otherParams拼接
* @param separator entry之间的连接符
* @param keyValueSeparator kv之间的连接符
* @param predicate 键值对过滤
* @param otherParams 其它附加参数字符串例如密钥
* @return 连接后的字符串map和otherParams为空返回""
* @since 3.1.1
*/
public static <K, V> String join(final Map<K, V> map, final String separator, final String keyValueSeparator,
final Predicate<Entry<K, V>> predicate, final String... otherParams) {
return MapJoiner.of(separator, keyValueSeparator)
.append(map, predicate)
.append(otherParams)
.toString();
}
// ----------------------------------------------------------------------------------------------- filter

View File

@ -9,6 +9,7 @@ import cn.hutool.core.util.ObjUtil;
import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;
/**
@ -196,7 +197,14 @@ public class StrJoiner implements Appendable, Serializable {
}
/**
* 追加对象到拼接器中
* 追加对象到拼接器中支持<br>
* <ul>
* <li>null按照 {@link #nullMode} 策略追加</li>
* <li>array逐个追加</li>
* <li>{@link Iterator}逐个追加</li>
* <li>{@link Iterable}逐个追加</li>
* <li>{@link Map.Entry}追加键分隔符再追加值</li>
* </ul>
*
* @param obj 对象支持数组集合等
* @return this
@ -210,6 +218,9 @@ public class StrJoiner implements Appendable, Serializable {
append((Iterator<?>) obj);
} else if (obj instanceof Iterable) {
append(((Iterable<?>) obj).iterator());
}else if (obj instanceof Map.Entry) {
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
append(entry.getKey()).append(entry.getValue());
} else {
append(ObjUtil.toString(obj));
}

View File

@ -0,0 +1,25 @@
package cn.hutool.core.map;
import org.junit.Assert;
import org.junit.Test;
public class MapJoinerTest {
@Test
public void joinMapTest(){
final Dict v1 = Dict.of().set("id", 12).set("name", "张三").set("age", 23);
final MapJoiner joiner = MapJoiner.of("+", "-");
joiner.append(v1, null);
Assert.assertEquals("id-12+name-张三+age-23", joiner.toString());
}
@Test
public void joinMapWithPredicateTest(){
final Dict v1 = Dict.of().set("id", 12).set("name", "张三").set("age", 23);
final MapJoiner joiner = MapJoiner.of("+", "-");
joiner.append(v1, (entry)->"age".equals(entry.getKey()));
Assert.assertEquals("age-23", joiner.toString());
}
}

View File

@ -240,4 +240,11 @@ public class MapUtilTest {
Assert.assertTrue(v2s.contains(13));
Assert.assertTrue(v2s.contains("李四"));
}
@Test
public void joinIgnoreNullTest() {
final Dict v1 = Dict.of().set("id", 12).set("name", "张三").set("age", null);
final String s = MapUtil.joinIgnoreNull(v1, ",", "=");
Assert.assertEquals("id=12,name=张三", s);
}
}