diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java index 16d91c494..6ce75c012 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/iter/IterUtil.java @@ -183,7 +183,7 @@ public class IterUtil { /** * 获取指定Bean列表中某个字段,生成新的列表 * - * @param 返回元素类型 + * @param 返回元素类型 * @param 对象类型 * @param iterable 对象列表 * @param fieldName 字段名(会通过反射获取其值) @@ -197,7 +197,7 @@ public class IterUtil { /** * 获取指定Bean列表中某个字段,生成新的列表 * - * @param 返回元素类型 + * @param 返回元素类型 * @param 对象类型 * @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 元素类型 * @return 元素,找不到元素返回{@code null} + * @throws IndexOutOfBoundsException index < 0时报错 * @since 5.8.0 */ public static E get(final Iterator iterator, int index) throws IndexOutOfBoundsException { diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapJoiner.java b/hutool-core/src/main/java/cn/hutool/core/map/MapJoiner.java new file mode 100755 index 000000000..e3b127687 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapJoiner.java @@ -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拼接器,可以拼接包括Map、Entry列表等。 + * + * @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 键类型 + * @param 值类型 + * @param map Map + * @param predicate Map过滤器 + * @return this + */ + public MapJoiner append(final Map map, final Predicate> predicate) { + return append(map.entrySet().iterator(), predicate); + } + + /** + * 追加Entry列表 + * + * @param 键类型 + * @param 值类型 + * @param parts Entry列表 + * @param predicate Map过滤器 + * @return this + */ + public MapJoiner append(final Iterator> parts, final Predicate> predicate) { + if (null == parts) { + return this; + } + + Map.Entry 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(); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java index 17cd8a148..b5d337e9d 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java @@ -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 String join(final Map 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 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 String join(final Map 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 键类型 + * @param 值类型 + * @param map Map,为空返回otherParams拼接 + * @param separator entry之间的连接符 + * @param keyValueSeparator kv之间的连接符 + * @param predicate 键值对过滤 + * @param otherParams 其它附加参数字符串(例如密钥) + * @return 连接后的字符串,map和otherParams为空返回"" + * @since 3.1.1 + */ + public static String join(final Map map, final String separator, final String keyValueSeparator, + final Predicate> predicate, final String... otherParams) { + return MapJoiner.of(separator, keyValueSeparator) + .append(map, predicate) + .append(otherParams) + .toString(); } // ----------------------------------------------------------------------------------------------- filter diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java b/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java index f2d740fc7..16bd4cee5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java @@ -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 { } /** - * 追加对象到拼接器中 + * 追加对象到拼接器中,支持:
+ *
    + *
  • null,按照 {@link #nullMode} 策略追加
  • + *
  • array,逐个追加
  • + *
  • {@link Iterator},逐个追加
  • + *
  • {@link Iterable},逐个追加
  • + *
  • {@link Map.Entry},追加键,分隔符,再追加值
  • + *
* * @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)); } diff --git a/hutool-core/src/test/java/cn/hutool/core/map/MapJoinerTest.java b/hutool-core/src/test/java/cn/hutool/core/map/MapJoinerTest.java new file mode 100755 index 000000000..96c6ee2d1 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/map/MapJoinerTest.java @@ -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()); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java index 868f6c753..27cfa79f0 100644 --- a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java @@ -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); + } }