mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add sort
This commit is contained in:
parent
0189de2dad
commit
0344982767
@ -23,6 +23,7 @@
|
||||
* 【core 】 DateUtil增加rangeContains、rangeNotContains(pr#537@Gitee)
|
||||
* 【core 】 Resource增加isModified默认方法
|
||||
* 【core 】 增加VfsResource
|
||||
* 【json 】 JSONConfig增加setKeyComparator、setNatureKeyComparator方法,支持自定义排序(issue#I4RBZ4@Gitee)
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github)
|
||||
|
@ -11,6 +11,18 @@ import java.util.function.Function;
|
||||
*/
|
||||
public class CompareUtil {
|
||||
|
||||
/**
|
||||
* 获取自然排序器,即默认排序器
|
||||
*
|
||||
* @param <E> 排序节点类型
|
||||
* @return 默认排序器
|
||||
* @since 5.7.21
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E extends Comparable<? super E>> Comparator<E> naturalComparator() {
|
||||
return ComparableComparator.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象比较,比较结果取决于comparator,如果被比较对象为null,传入的comparator对象应处理此情况<br>
|
||||
* 如果传入comparator为null,则使用默认规则比较(此时被比较对象必须实现Comparable接口)
|
||||
|
73
hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java
Executable file
73
hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java
Executable file
@ -0,0 +1,73 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 忽略大小写的{@link TreeMap}<br>
|
||||
* 对KEY忽略大小写,get("Value")和get("value")获得的值相同,put进入的值也会被覆盖
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public class CaseInsensitiveTreeMap<K, V> extends CustomKeyMap<K, V> {
|
||||
private static final long serialVersionUID = 4043263744224569870L;
|
||||
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public CaseInsensitiveTreeMap() {
|
||||
this((Comparator<? super K>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public CaseInsensitiveTreeMap(Map<? extends K, ? extends V> m) {
|
||||
this();
|
||||
this.putAll(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public CaseInsensitiveTreeMap(SortedMap<? extends K, ? extends V> m) {
|
||||
super(new TreeMap<K, V>(m));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param comparator 比较器,{@code null}表示使用默认比较器
|
||||
*/
|
||||
public CaseInsensitiveTreeMap(Comparator<? super K> comparator) {
|
||||
super(new TreeMap<>(comparator));
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
/**
|
||||
* 将Key转为小写
|
||||
*
|
||||
* @param key KEY
|
||||
* @return 小写KEY
|
||||
*/
|
||||
@Override
|
||||
protected Object customKey(Object key) {
|
||||
if (key instanceof CharSequence) {
|
||||
key = key.toString().toLowerCase();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* JSON配置项
|
||||
@ -15,6 +18,10 @@ public class JSONConfig implements Serializable {
|
||||
* 是否有序,顺序按照加入顺序排序,只针对JSONObject有效
|
||||
*/
|
||||
private boolean order;
|
||||
/**
|
||||
* 键排序规则,{@code null}表示不排序,不排序情况下,如果{@link #order}为{@code true}按照加入顺序排序,否则按照hash排序
|
||||
*/
|
||||
private Comparator<String> keyComparator;
|
||||
/**
|
||||
* 是否忽略转换过程中的异常
|
||||
*/
|
||||
@ -70,6 +77,40 @@ public class JSONConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取键排序规则<br>
|
||||
* 键排序规则,{@code null}表示不排序,不排序情况下,如果{@link #order}为{@code true}按照加入顺序排序,否则按照hash排序
|
||||
*
|
||||
* @return 键排序规则
|
||||
* @since 5.7.21
|
||||
*/
|
||||
public Comparator<String> getKeyComparator() {
|
||||
return this.keyComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自然排序,即按照字母顺序排序
|
||||
*
|
||||
* @return this
|
||||
* @since 5.7.21
|
||||
*/
|
||||
public JSONConfig setNatureKeyComparator() {
|
||||
return setKeyComparator(CompareUtil.naturalComparator());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置键排序规则<br>
|
||||
* 键排序规则,{@code null}表示不排序,不排序情况下,如果{@link #order}为{@code true}按照加入顺序排序,否则按照hash排序
|
||||
*
|
||||
* @param keyComparator 键排序规则
|
||||
* @return this
|
||||
* @since 5.7.21
|
||||
*/
|
||||
public JSONConfig setKeyComparator(Comparator<String> keyComparator) {
|
||||
this.keyComparator = keyComparator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否忽略转换过程中的异常
|
||||
*
|
||||
|
@ -10,6 +10,7 @@ import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.lang.mutable.MutablePair;
|
||||
import cn.hutool.core.map.CaseInsensitiveLinkedMap;
|
||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||
import cn.hutool.core.map.CaseInsensitiveTreeMap;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@ -25,10 +26,12 @@ import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* JSON对象<br>
|
||||
@ -121,9 +124,21 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
|
||||
config = JSONConfig.create();
|
||||
}
|
||||
if (config.isIgnoreCase()) {
|
||||
this.rawHashMap = config.isOrder() ? new CaseInsensitiveLinkedMap<>(capacity) : new CaseInsensitiveMap<>(capacity);
|
||||
final Comparator<String> keyComparator = config.getKeyComparator();
|
||||
if(null != keyComparator){
|
||||
// 比较器存在情况下,isOrder无效
|
||||
this.rawHashMap = new CaseInsensitiveTreeMap<>(keyComparator);
|
||||
}else{
|
||||
this.rawHashMap = config.isOrder() ? new CaseInsensitiveLinkedMap<>(capacity) : new CaseInsensitiveMap<>(capacity);
|
||||
}
|
||||
} else {
|
||||
this.rawHashMap = MapUtil.newHashMap(capacity, config.isOrder());
|
||||
final Comparator<String> keyComparator = config.getKeyComparator();
|
||||
if(null != keyComparator){
|
||||
// 比较器存在情况下,isOrder无效
|
||||
this.rawHashMap = new TreeMap<>(keyComparator);
|
||||
}else{
|
||||
this.rawHashMap = MapUtil.newHashMap(capacity, config.isOrder());
|
||||
}
|
||||
}
|
||||
this.config = config;
|
||||
}
|
||||
@ -178,7 +193,8 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
|
||||
public JSONObject(Object source, boolean ignoreNullValue, boolean isOrder) {
|
||||
this(source, JSONConfig.create().setOrder(isOrder)//
|
||||
.setIgnoreCase((source instanceof CaseInsensitiveMap))//
|
||||
.setIgnoreNullValue(ignoreNullValue));
|
||||
.setIgnoreNullValue(ignoreNullValue)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
18
hutool-json/src/test/java/cn/hutool/json/IssueI4RBZ4Test.java
Executable file
18
hutool-json/src/test/java/cn/hutool/json/IssueI4RBZ4Test.java
Executable file
@ -0,0 +1,18 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I4RBZ4
|
||||
*/
|
||||
public class IssueI4RBZ4Test {
|
||||
|
||||
@Test
|
||||
public void sortTest(){
|
||||
String jsonStr = "{\"id\":\"123\",\"array\":[1,2,3],\"outNum\":356,\"body\":{\"ava1\":\"20220108\",\"use\":1,\"ava2\":\"20230108\"},\"name\":\"John\"}";
|
||||
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(jsonStr, JSONConfig.create().setNatureKeyComparator());
|
||||
Assert.assertEquals("{\"array\":[1,2,3],\"body\":{\"ava1\":\"20220108\",\"ava2\":\"20230108\",\"use\":1},\"id\":\"123\",\"name\":\"John\",\"outNum\":356}", jsonObject.toString());
|
||||
}
|
||||
}
|
@ -1,18 +1,19 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class issues1881Test {
|
||||
public class Issues1881Test {
|
||||
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
public class ThingsHolderContactVO implements Serializable {
|
||||
static class ThingsHolderContactVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8727337936070932370L;
|
||||
private Long id;
|
||||
@ -30,6 +31,6 @@ public class issues1881Test {
|
||||
holderContactVOList.add(new ThingsHolderContactVO().setId(1L).setName("1"));
|
||||
holderContactVOList.add(new ThingsHolderContactVO().setId(2L).setName("2"));
|
||||
|
||||
Console.log(JSONUtil.parseArray(holderContactVOList));
|
||||
Assert.assertEquals("[{\"name\":\"1\",\"id\":1},{\"name\":\"2\",\"id\":2}]", JSONUtil.parseArray(holderContactVOList).toString());
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@ -33,6 +34,7 @@ public class JSONStrFormatterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void formatTest4(){
|
||||
String jsonStr = "{\"employees\":[{\"firstName\":\"Bill\",\"lastName\":\"Gates\"},{\"firstName\":\"George\",\"lastName\":\"Bush\"},{\"firstName\":\"Thomas\",\"lastName\":\"Carter\"}]}";
|
||||
Console.log(JSONUtil.formatJsonStr(jsonStr));
|
||||
|
@ -36,7 +36,7 @@ public class JSONUtilTest {
|
||||
@Test(expected = JSONException.class)
|
||||
public void parseNumberTest() {
|
||||
JSONArray json = JSONUtil.parseArray(123L);
|
||||
Console.log(json);
|
||||
Assert.assertNotNull(json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user