mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
fix bug and add method
This commit is contained in:
parent
d15ec3c647
commit
efedd36696
@ -6,7 +6,11 @@
|
||||
## 5.3.1 (2020-04-11)
|
||||
|
||||
### 新特性
|
||||
* 【core 】 ListUtil、MapUtil、CollUtil增加empty方法
|
||||
|
||||
### Bug修复
|
||||
* 【json 】 修复解析JSON字符串时配置无法传递问题
|
||||
* 【core 】 修复ServletUtil.readCookieMap空指针问题(issue#827@Github)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -38,8 +38,10 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
@ -2362,15 +2364,14 @@ public class CollUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环遍历Map,使用{@link KVConsumer} 接受遍历的每条数据,并针对每条数据做处理
|
||||
* 循环遍历Map,使用{@link KVConsumer} 接受遍历的每条数据,并针对每条数据做处理<br>
|
||||
* 和JDK8中的map.forEach不同的是,此方法支持index
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param map {@link Map}
|
||||
* @param kvConsumer {@link KVConsumer} 遍历的每条数据处理器
|
||||
* @deprecated JDK8+中使用map.forEach
|
||||
*/
|
||||
@Deprecated
|
||||
public static <K, V> void forEach(Map<K, V> map, KVConsumer<K, V> kvConsumer) {
|
||||
int index = 0;
|
||||
for (Entry<K, V> entry : map.entrySet()) {
|
||||
@ -2561,6 +2562,43 @@ public class CollUtil {
|
||||
return Collections.unmodifiableCollection(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的集合类型,返回对应的空集合,支持类型包括:
|
||||
* *
|
||||
* <pre>
|
||||
* 1. NavigableSet
|
||||
* 2. SortedSet
|
||||
* 3. Set
|
||||
* 4. List
|
||||
* </pre>
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @param <T> 集合类型
|
||||
* @return 空集合
|
||||
* @since 5.3.1
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E, T extends Collection<E>> T empty(Class<?> collectionClass) {
|
||||
if (null == collectionClass) {
|
||||
return (T) Collections.emptyList();
|
||||
}
|
||||
|
||||
if (Set.class.isAssignableFrom(collectionClass)) {
|
||||
if (NavigableSet.class == collectionClass) {
|
||||
return (T) Collections.emptyNavigableSet();
|
||||
} else if (SortedSet.class == collectionClass) {
|
||||
return (T) Collections.emptySortedSet();
|
||||
} else {
|
||||
return (T) Collections.emptySet();
|
||||
}
|
||||
} else if (List.class.isAssignableFrom(collectionClass)) {
|
||||
return (T) Collections.emptyList();
|
||||
}
|
||||
|
||||
// 不支持空集合的集合类型
|
||||
throw new IllegalArgumentException(StrUtil.format("[{}] is not support to get empty!", collectionClass));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------- Interface start
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@ import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@ -676,4 +677,16 @@ public class IterUtil {
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个空Iterator
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @return 空Iterator
|
||||
* @see Collections#emptyIterator()
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static <T> Iterator<T> empty() {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
||||
|
@ -425,13 +425,13 @@ public class ListUtil {
|
||||
/**
|
||||
* 获取匹配规则定义中匹配到元素的所有位置
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param list 列表
|
||||
* @param <T> 元素类型
|
||||
* @param list 列表
|
||||
* @param matcher 匹配器,为空则全部匹配
|
||||
* @return 位置数组
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public static <T> int[] indexOfAll(List<T> list, Matcher<T> matcher){
|
||||
public static <T> int[] indexOfAll(List<T> list, Matcher<T> matcher) {
|
||||
final List<Integer> indexList = new ArrayList<>();
|
||||
if (null != list) {
|
||||
int index = 0;
|
||||
@ -448,12 +448,23 @@ public class ListUtil {
|
||||
/**
|
||||
* 将对应List转换为不可修改的List
|
||||
*
|
||||
* @param list Map
|
||||
* @param <T> 元素类型
|
||||
* @return 不修改Map
|
||||
* @param list List
|
||||
* @param <T> 元素类型
|
||||
* @return 不可修改List
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <T> List<T> unmodifiable(List<T> list) {
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个空List
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @return 空的List
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <T> List<T> empty() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -687,8 +689,8 @@ public class MapUtil {
|
||||
* @param <T> 键和值类型
|
||||
* @param map Map对象,键值类型必须一致
|
||||
* @return 互换后的Map
|
||||
* @since 3.2.2
|
||||
* @see #inverse(Map)
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public static <T> Map<T, T> reverse(Map<T, T> map) {
|
||||
return filter(map, (Editor<Entry<T, T>>) t -> new Entry<T, T>() {
|
||||
@ -1067,4 +1069,50 @@ public class MapUtil {
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个空Map
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @return 空Map
|
||||
* @see Collections#emptyMap()
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static <K, V> Map<K, V> empty() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的Map类型不同,返回对应类型的空Map,支持类型包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1. NavigableMap
|
||||
* 2. SortedMap
|
||||
* 3. Map
|
||||
* </pre>
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param <T> Map类型
|
||||
* @param mapClass Map类型,null返回默认的Map
|
||||
* @return 空Map
|
||||
* @since 5.3.1
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V, T extends Map<K, V>> T empty(Class<?> mapClass) {
|
||||
if (null == mapClass) {
|
||||
return (T) Collections.emptyMap();
|
||||
}
|
||||
if (NavigableMap.class == mapClass) {
|
||||
return (T) Collections.emptyNavigableMap();
|
||||
} else if (SortedMap.class == mapClass) {
|
||||
return (T) Collections.emptySortedMap();
|
||||
} else if (Map.class == mapClass) {
|
||||
return (T) Collections.emptyMap();
|
||||
}
|
||||
|
||||
// 不支持空集合的集合类型
|
||||
throw new IllegalArgumentException(StrUtil.format("[{}] is not support to get empty!", mapClass));
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@ -715,7 +716,7 @@ public class NetUtil {
|
||||
*/
|
||||
public static List<HttpCookie> parseCookies(String cookieStr){
|
||||
if(StrUtil.isBlank(cookieStr)){
|
||||
return CollUtil.newArrayList();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return HttpCookie.parse(cookieStr);
|
||||
}
|
||||
|
@ -5,11 +5,14 @@ import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.lang.Editor;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@ -20,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* 集合工具类单元测试
|
||||
@ -179,7 +183,6 @@ public class CollUtilTest {
|
||||
map.put("c", "3");
|
||||
|
||||
final String[] result = new String[1];
|
||||
//noinspection deprecation
|
||||
CollUtil.forEach(map, (key, value, index) -> {
|
||||
if (key.equals("a")) {
|
||||
result[0] = value;
|
||||
@ -304,6 +307,20 @@ public class CollUtilTest {
|
||||
Assert.assertEquals(new Integer(14), map.get("王五"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyTest() {
|
||||
final SortedSet<String> emptySortedSet = CollUtil.empty(SortedSet.class);
|
||||
Assert.assertEquals(Collections.emptySortedSet(), emptySortedSet);
|
||||
|
||||
final Set<String> emptySet = CollUtil.empty(Set.class);
|
||||
Assert.assertEquals(Collections.emptySet(), emptySet);
|
||||
|
||||
final List<String> emptyList = CollUtil.empty(List.class);
|
||||
Assert.assertEquals(Collections.emptyList(), emptyList);
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class TestBean {
|
||||
private String name;
|
||||
private int age;
|
||||
@ -313,41 +330,6 @@ public class CollUtilTest {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public TestBean(String name, int age, Date createTime) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestBeans [name=" + name + ", age=" + age + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -87,7 +87,8 @@ public class CRUDTest {
|
||||
|
||||
@Test
|
||||
public void findInTest2() throws SQLException {
|
||||
List<Entity> results = db.findAll(Entity.create("user").set("id", new Condition("id", new long[]{1, 2, 3})));
|
||||
List<Entity> results = db.findAll(Entity.create("user")
|
||||
.set("id", new Condition("id", new long[]{1, 2, 3})));
|
||||
Assert.assertEquals(2, results.size());
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.net.multipart.MultipartFormData;
|
||||
import cn.hutool.core.net.multipart.UploadSetting;
|
||||
@ -418,6 +419,11 @@ public class ServletUtil {
|
||||
* @return Cookie map
|
||||
*/
|
||||
public static Map<String, Cookie> readCookieMap(HttpServletRequest httpServletRequest) {
|
||||
final Cookie[] cookies = httpServletRequest.getCookies();
|
||||
if(ArrayUtil.isEmpty(cookies)){
|
||||
return MapUtil.empty();
|
||||
}
|
||||
|
||||
return IterUtil.toMap(
|
||||
new ArrayIter<>(httpServletRequest.getCookies()),
|
||||
new CaseInsensitiveMap<>(),
|
||||
|
@ -206,8 +206,13 @@ final class InternalJSONUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认情况下是否忽略null值的策略选择<br>
|
||||
* JavaBean默认忽略null值,其它对象不忽略
|
||||
* 默认情况下是否忽略null值的策略选择,以下对象不忽略null值,其它对象忽略:
|
||||
*
|
||||
* <pre>
|
||||
* 1. CharSequence
|
||||
* 2. JSONTokener
|
||||
* 3. Map
|
||||
* </pre>
|
||||
*
|
||||
* @param obj 需要检查的对象
|
||||
* @return 是否忽略null值
|
||||
@ -234,13 +239,13 @@ final class InternalJSONUtil {
|
||||
|
||||
//默认使用时间戳
|
||||
long timeMillis;
|
||||
if(dateObj instanceof TemporalAccessor){
|
||||
timeMillis = DateUtil.toInstant((TemporalAccessor)dateObj).toEpochMilli();
|
||||
} else if(dateObj instanceof Date){
|
||||
if (dateObj instanceof TemporalAccessor) {
|
||||
timeMillis = DateUtil.toInstant((TemporalAccessor) dateObj).toEpochMilli();
|
||||
} else if (dateObj instanceof Date) {
|
||||
timeMillis = ((Date) dateObj).getTime();
|
||||
} else if(dateObj instanceof Calendar){
|
||||
} else if (dateObj instanceof Calendar) {
|
||||
timeMillis = ((Calendar) dateObj).getTimeInMillis();
|
||||
} else{
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported Date type: " + dateObj.getClass());
|
||||
}
|
||||
return String.valueOf(timeMillis);
|
||||
|
@ -20,7 +20,7 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.RandomAccess;
|
||||
|
||||
import static cn.hutool.json.JSONConverter.*;
|
||||
import static cn.hutool.json.JSONConverter.jsonConvert;
|
||||
|
||||
/**
|
||||
* JSON数组<br>
|
||||
|
@ -124,7 +124,8 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
|
||||
* <li>value为Map,将键值对加入JSON对象</li>
|
||||
* <li>value为JSON字符串(CharSequence),使用JSONTokener解析</li>
|
||||
* <li>value为JSONTokener,直接解析</li>
|
||||
* <li>value为普通JavaBean,如果为普通的JavaBean,调用其getters方法(getXXX或者isXXX)获得值,加入到JSON对象。例如:如果JavaBean对象中有个方法getName(),值为"张三",获得的键值对为:name: "张三"</li>
|
||||
* <li>value为普通JavaBean,如果为普通的JavaBean,调用其getters方法(getXXX或者isXXX)获得值,加入到JSON对象。
|
||||
* 例如:如果JavaBean对象中有个方法getName(),值为"张三",获得的键值对为:name: "张三"</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param source JavaBean或者Map对象或者String
|
||||
|
@ -45,7 +45,7 @@ public class JSONTokener {
|
||||
/**
|
||||
* JSON配置
|
||||
*/
|
||||
private JSONConfig config;
|
||||
private final JSONConfig config;
|
||||
|
||||
// ------------------------------------------------------------------------------------ Constructor start
|
||||
|
||||
@ -63,6 +63,7 @@ public class JSONTokener {
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.line = 1;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,17 @@ public class JSONArrayTest {
|
||||
Assert.assertEquals(array.get(0), "value1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseWithNullTest() {
|
||||
String jsonStr = "[{\"grep\":\"4.8\",\"result\":\"右\"},{\"grep\":\"4.8\",\"result\":null}]";
|
||||
JSONArray jsonArray = JSONUtil.parseArray(jsonStr);
|
||||
Assert.assertFalse(jsonArray.getJSONObject(1).containsKey("result"));
|
||||
|
||||
// 不忽略null,则null的键值对被保留
|
||||
jsonArray = new JSONArray(jsonStr, false);
|
||||
Assert.assertTrue(jsonArray.getJSONObject(1).containsKey("result"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseFileTest() {
|
||||
JSONArray array = JSONUtil.readJSONArray(FileUtil.file("exam_test.json"), CharsetUtil.CHARSET_UTF_8);
|
||||
|
@ -186,11 +186,11 @@ public class JSONObjectTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBeanTest3() {
|
||||
public void toBeanWithNullTest() {
|
||||
String jsonStr = "{'data':{'userName':'ak','password': null}}";
|
||||
Console.log(JSONUtil.parseObj(jsonStr));
|
||||
UserWithMap user = JSONUtil.toBean(JSONUtil.parseObj(jsonStr), UserWithMap.class);
|
||||
// Bean默认忽略null
|
||||
Assert.assertFalse(user.getData().containsKey("password"));
|
||||
Assert.assertTrue(user.getData().containsKey("password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user