mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
add sortJoin
This commit is contained in:
parent
da39e9e646
commit
3511952a35
@ -10,6 +10,7 @@
|
||||
* 【core】 XmlUtil中mapToStr支持namespace(pr#599@Github)
|
||||
* 【core】 ZipUtil修改策略:默认关闭输入流(issue#604@Github)
|
||||
* 【core】 改进CsvReader,支持RowHandler按行处理(issue#608@Github)
|
||||
* 【core】 增加MapUtil.sortJoin,改进SecureUtil.signParams支持补充字符串(issue#606@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【core】 解决ConcurrentHashSet不能序列化的问题(issue#600@Github)
|
||||
|
@ -492,11 +492,28 @@ public class MapUtil {
|
||||
* @param map Map
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 连接字符串
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public static <K, V> String join(Map<K, V> map, String separator, String keyValueSeparator) {
|
||||
return join(map, separator, keyValueSeparator, false);
|
||||
public static <K, V> String join(Map<K, V> map, String separator, String keyValueSeparator, String... otherParams) {
|
||||
return join(map, separator, keyValueSeparator, false, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数排序后拼接为字符串,常用于签名
|
||||
*
|
||||
* @param params 参数
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param isIgnoreNull 是否忽略null的键和值
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名字符串
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public static String sortJoin(Map<?, ?> params, String separator, String keyValueSeparator, boolean isIgnoreNull,
|
||||
String... otherParams) {
|
||||
return join(sort(params), separator, keyValueSeparator, isIgnoreNull, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -507,11 +524,12 @@ public class MapUtil {
|
||||
* @param map Map
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 连接后的字符串
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public static <K, V> String joinIgnoreNull(Map<K, V> map, String separator, String keyValueSeparator) {
|
||||
return join(map, separator, keyValueSeparator, true);
|
||||
public static <K, V> String joinIgnoreNull(Map<K, V> map, String separator, String keyValueSeparator, String... otherParams) {
|
||||
return join(map, separator, keyValueSeparator, true, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -519,24 +537,33 @@ public class MapUtil {
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param map Map
|
||||
* @param map Map,为空返回otherParams拼接
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param isIgnoreNull 是否忽略null的键和值
|
||||
* @return 连接后的字符串
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 连接后的字符串,map和otherParams为空返回""
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public static <K, V> String join(Map<K, V> map, String separator, String keyValueSeparator, boolean isIgnoreNull) {
|
||||
public static <K, V> String join(Map<K, V> map, String separator, String keyValueSeparator, boolean isIgnoreNull, String... otherParams) {
|
||||
final StringBuilder strBuilder = StrUtil.builder();
|
||||
boolean isFirst = true;
|
||||
for (Entry<K, V> entry : map.entrySet()) {
|
||||
if (false == isIgnoreNull || entry.getKey() != null && entry.getValue() != null) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
strBuilder.append(separator);
|
||||
if(isNotEmpty(map)){
|
||||
for (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()));
|
||||
}
|
||||
strBuilder.append(Convert.toStr(entry.getKey())).append(keyValueSeparator).append(Convert.toStr(entry.getValue()));
|
||||
}
|
||||
}
|
||||
// 补充其它字符串到末尾,默认无分隔符
|
||||
if (ArrayUtil.isNotEmpty(otherParams)) {
|
||||
for (String otherParam : otherParams) {
|
||||
strBuilder.append(otherParam);
|
||||
}
|
||||
}
|
||||
return strBuilder.toString();
|
||||
@ -687,13 +714,17 @@ public class MapUtil {
|
||||
*
|
||||
* @param <K> key的类型
|
||||
* @param <V> value的类型
|
||||
* @param map Map
|
||||
* @param map Map,为null返回null
|
||||
* @param comparator Key比较器
|
||||
* @return TreeMap
|
||||
* @return TreeMap,map为null返回null
|
||||
* @see #newTreeMap(Map, Comparator)
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static <K, V> TreeMap<K, V> sort(Map<K, V> map, Comparator<? super K> comparator) {
|
||||
if(null == map){
|
||||
return null;
|
||||
}
|
||||
|
||||
TreeMap<K, V> result;
|
||||
if (map instanceof TreeMap) {
|
||||
// 已经是可排序Map,此时只有比较器一致才返回原map
|
||||
|
@ -1,14 +1,15 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Editor;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapUtilTest {
|
||||
|
||||
@ -20,16 +21,7 @@ public class MapUtilTest {
|
||||
map.put("c", "3");
|
||||
map.put("d", "4");
|
||||
|
||||
Map<String, String> map2 = MapUtil.filter(map, new Filter<Entry<String, String>>() {
|
||||
|
||||
@Override
|
||||
public boolean accept(Entry<String, String> t) {
|
||||
if (Convert.toInt(t.getValue()) % 2 == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Map<String, String> map2 = MapUtil.filter(map, (Filter<Entry<String, String>>) t -> Convert.toInt(t.getValue()) % 2 == 0);
|
||||
|
||||
Assert.assertEquals(2, map2.size());
|
||||
|
||||
@ -45,14 +37,10 @@ public class MapUtilTest {
|
||||
map.put("c", "3");
|
||||
map.put("d", "4");
|
||||
|
||||
Map<String, String> map2 = MapUtil.filter(map, new Editor<Entry<String, String>>() {
|
||||
|
||||
@Override
|
||||
public Entry<String, String> edit(Entry<String, String> t) {
|
||||
// 修改每个值使之*10
|
||||
t.setValue(t.getValue() + "0");
|
||||
return t;
|
||||
}
|
||||
Map<String, String> map2 = MapUtil.filter(map, (Editor<Entry<String, String>>) t -> {
|
||||
// 修改每个值使之*10
|
||||
t.setValue(t.getValue() + "0");
|
||||
return t;
|
||||
});
|
||||
|
||||
Assert.assertEquals(4, map2.size());
|
||||
@ -97,4 +85,21 @@ public class MapUtilTest {
|
||||
Assert.assertEquals("d", objectArray[3][0]);
|
||||
Assert.assertEquals("4", objectArray[3][1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortJoinTest(){
|
||||
Map<String, String> build = MapUtil.builder(new HashMap<String, String>())
|
||||
.put("key1", "value1")
|
||||
.put("key3", "value3")
|
||||
.put("key2", "value2").build();
|
||||
|
||||
String join1 = MapUtil.sortJoin(build, StrUtil.EMPTY, StrUtil.EMPTY, false);
|
||||
Assert.assertEquals("key1value1key2value2key3value3", join1);
|
||||
|
||||
String join2 = MapUtil.sortJoin(build, StrUtil.EMPTY, StrUtil.EMPTY, false, "123");
|
||||
Assert.assertEquals("key1value1key2value2key3value3123", join2);
|
||||
|
||||
String join3 = MapUtil.sortJoin(build, StrUtil.EMPTY, StrUtil.EMPTY, false, "123", "abc");
|
||||
Assert.assertEquals("key1value1key2value2key3value3123abc", join3);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@ -825,13 +826,14 @@ public final class SecureUtil {
|
||||
* 参数签名为对Map参数按照key的顺序排序后拼接为字符串,然后根据提供的签名算法生成签名字符串<br>
|
||||
* 拼接后的字符串键值对之间无符号,键值对之间无符号,忽略null值
|
||||
*
|
||||
* @param crypto 对称加密算法
|
||||
* @param params 参数
|
||||
* @param crypto 对称加密算法
|
||||
* @param params 参数
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParams(SymmetricCrypto crypto, Map<?, ?> params) {
|
||||
return signParams(crypto, params, StrUtil.EMPTY, StrUtil.EMPTY, true);
|
||||
public static String signParams(SymmetricCrypto crypto, Map<?, ?> params, String... otherParams) {
|
||||
return signParams(crypto, params, StrUtil.EMPTY, StrUtil.EMPTY, true, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -843,15 +845,13 @@ public final class SecureUtil {
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param isIgnoreNull 是否忽略null的键和值
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParams(SymmetricCrypto crypto, Map<?, ?> params, String separator, String keyValueSeparator, boolean isIgnoreNull) {
|
||||
if (MapUtil.isEmpty(params)) {
|
||||
return null;
|
||||
}
|
||||
String paramsStr = MapUtil.join(MapUtil.sort(params), separator, keyValueSeparator, isIgnoreNull);
|
||||
return crypto.encryptHex(paramsStr);
|
||||
public static String signParams(SymmetricCrypto crypto, Map<?, ?> params, String separator,
|
||||
String keyValueSeparator, boolean isIgnoreNull, String... otherParams) {
|
||||
return crypto.encryptHex(MapUtil.sortJoin(params, separator, keyValueSeparator, isIgnoreNull, otherParams));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -859,12 +859,13 @@ public final class SecureUtil {
|
||||
* 参数签名为对Map参数按照key的顺序排序后拼接为字符串,然后根据提供的签名算法生成签名字符串<br>
|
||||
* 拼接后的字符串键值对之间无符号,键值对之间无符号,忽略null值
|
||||
*
|
||||
* @param params 参数
|
||||
* @param params 参数
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParamsMd5(Map<?, ?> params) {
|
||||
return signParams(DigestAlgorithm.MD5, params);
|
||||
public static String signParamsMd5(Map<?, ?> params, String... otherParams) {
|
||||
return signParams(DigestAlgorithm.MD5, params, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -872,12 +873,13 @@ public final class SecureUtil {
|
||||
* 参数签名为对Map参数按照key的顺序排序后拼接为字符串,然后根据提供的签名算法生成签名字符串<br>
|
||||
* 拼接后的字符串键值对之间无符号,键值对之间无符号,忽略null值
|
||||
*
|
||||
* @param params 参数
|
||||
* @param params 参数
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.8
|
||||
*/
|
||||
public static String signParamsSha1(Map<?, ?> params) {
|
||||
return signParams(DigestAlgorithm.SHA1, params);
|
||||
public static String signParamsSha1(Map<?, ?> params, String... otherParams) {
|
||||
return signParams(DigestAlgorithm.SHA1, params, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -885,12 +887,13 @@ public final class SecureUtil {
|
||||
* 参数签名为对Map参数按照key的顺序排序后拼接为字符串,然后根据提供的签名算法生成签名字符串<br>
|
||||
* 拼接后的字符串键值对之间无符号,键值对之间无符号,忽略null值
|
||||
*
|
||||
* @param params 参数
|
||||
* @param params 参数
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParamsSha256(Map<?, ?> params) {
|
||||
return signParams(DigestAlgorithm.SHA256, params);
|
||||
public static String signParamsSha256(Map<?, ?> params, String... otherParams) {
|
||||
return signParams(DigestAlgorithm.SHA256, params, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -900,11 +903,12 @@ public final class SecureUtil {
|
||||
*
|
||||
* @param digestAlgorithm 摘要算法
|
||||
* @param params 参数
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParams(DigestAlgorithm digestAlgorithm, Map<?, ?> params) {
|
||||
return signParams(digestAlgorithm, params, StrUtil.EMPTY, StrUtil.EMPTY, true);
|
||||
public static String signParams(DigestAlgorithm digestAlgorithm, Map<?, ?> params, String... otherParams) {
|
||||
return signParams(digestAlgorithm, params, StrUtil.EMPTY, StrUtil.EMPTY, true, otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -916,15 +920,13 @@ public final class SecureUtil {
|
||||
* @param separator entry之间的连接符
|
||||
* @param keyValueSeparator kv之间的连接符
|
||||
* @param isIgnoreNull 是否忽略null的键和值
|
||||
* @param otherParams 其它附加参数字符串(例如密钥)
|
||||
* @return 签名
|
||||
* @since 4.0.1
|
||||
*/
|
||||
public static String signParams(DigestAlgorithm digestAlgorithm, Map<?, ?> params, String separator, String keyValueSeparator, boolean isIgnoreNull) {
|
||||
if (MapUtil.isEmpty(params)) {
|
||||
return null;
|
||||
}
|
||||
final String paramsStr = MapUtil.join(MapUtil.sort(params), separator, keyValueSeparator, isIgnoreNull);
|
||||
return new Digester(digestAlgorithm).digestHex(paramsStr);
|
||||
public static String signParams(DigestAlgorithm digestAlgorithm, Map<?, ?> params, String separator,
|
||||
String keyValueSeparator, boolean isIgnoreNull, String... otherParams) {
|
||||
return new Digester(digestAlgorithm).digestHex(MapUtil.sortJoin(params, separator, keyValueSeparator, isIgnoreNull, otherParams));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------- UUID
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.crypto.test;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -8,6 +9,9 @@ import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.Sign;
|
||||
import cn.hutool.crypto.asymmetric.SignAlgorithm;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 签名单元测试
|
||||
*
|
||||
@ -88,4 +92,18 @@ public class SignTest {
|
||||
boolean verify = sign.verify(data, signed);
|
||||
Assert.assertTrue(verify);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void signParamsTest(){
|
||||
Map<String, String> build = MapUtil.builder(new HashMap<String, String>())
|
||||
.put("key1", "value1")
|
||||
.put("key2", "value2").build();
|
||||
|
||||
String sign1 = SecureUtil.signParamsSha1(build);
|
||||
Assert.assertEquals("9ed30bfe2efbc7038a824b6c55c24a11bfc0dce5", sign1);
|
||||
String sign2 = SecureUtil.signParamsSha1(build, "12345678");
|
||||
Assert.assertEquals("944b68d94c952ec178c4caf16b9416b6661f7720", sign2);
|
||||
String sign3 = SecureUtil.signParamsSha1(build, "12345678", "abc");
|
||||
Assert.assertEquals("edee1b477af1b96ebd20fdf08d818f352928d25d", sign3);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user