Releases: ifeilong/feilong-core
1.11.1
本次升级共有 1
处变更, 具体参见 1.11.1 milestone
1.11.1 文档地址: http://feilong-core.mydoc.io/
[Feature] 🆕
- #733 MapUtil 新增 newConcurrentHashMap(int expectedSize)
[Update]
- none
[Remove]
- none
[Fix Bug] 🐛
- none
[javadoc]
- none
[test]
- none
[help wanted]
- none
1.11.0
本次升级共有 16
处变更, 具体参见 1.11.0 milestone
1.11.0 文档地址: http://feilong-core.mydoc.io/
首先预览下,本次发布的核心内容 :
CollectionUtil
添加删除 null 元素的功能- 重构DatePattern
[Feature] 🆕
- #731 新增
ReturnResultBuilder
- #730 新增
ReturnResult
- #728 新建
PartitionThreadExecutor
做为通用接口,适用于 spring实现 - #729 新建
ThreadUtil.execute(List<T>, int, PartitionRunnableBuilder<T>)
方法 - #723
CollectionUtil
添加删除 null 元素的功能
场景: 从list中删除 null 元素
List<String> list = toList("xinge", null, "feilong2", null, "feilong2");
List<String> removeList = CollectionsUtil.removeAllNull(list);
返回:
"xinge", "feilong2", "feilong2"
示例:
List<String> list = com.feilong.core.bean.ConvertUtil.toList("feilong", "", "xinge");
ConvertUtil.toString(list,",");
输出:
feilong,,xinge
你还可以使用这个方法来将集合换行输出,比如:
List<String> list = toList("飞龙", "小金", "四金", "金金金金");
LOGGER.debug(ConvertUtil.toString(list, System.lineSeparator()));
输出:
飞龙
小金
四金
金金金金
[Update]
- #716 重命名 DatePattern.CHINESE_COMMON_DATE 成 CHINESE_DATE
- #717 重命名 DatePattern.CHINESE_COMMON_DATE_AND_TIME 成 CHINESE_DATE_AND_TIME
- #714 DatePattern yyyyMMdd 格式重命名成 BASIC_ISO_DATE
- #715 DatePattern ddMMyyyyHHmmss 格式重命名 成 INDONESIA_DATE_AND_TIME
[Remove]
[Fix Bug] 🐛
- none
[javadoc]
- none
[test]
- none
[help wanted]
[log]
- #721
BeanUtil.populate
修改相关异常的message 信息
1.10.7
本次升级共有 25
处变更, 具体参见 1.10.7 milestone
1.10.7 文档地址: http://feilong-core.mydoc.io/
首先预览下,本次发布的核心内容 :
MapUtil
,CollectionsUtil
新增常用方法DatePattern
新增常用常量NumberUtil
新增常用常量 和常用比较方法AggregateUtil
groupCount 方法支持自定义分组
此外,补充大量的单元测试, 单元测试数量达到 1967
个, 代码覆盖率达到 91%
[Feature] 🆕
-
#691 新增
AggregateUtil.groupCount(Iterable<O>, String[], Map<String, Transformer<Object, Object>>)
方法 -
#689
AggregateUtil.groupCount
增加对范围的支持 -
#694 MapUtil 添加 newHashMap() 方法
-
#696 MapUtil 添加 newConcurrentHashMap() 方法
-
#695 MapUtil 添加 newLinkedHashMap() 方法
-
#697 MapUtil 添加 newTreeMap() 方法
-
#698 CollectionsUtil 新建一个常见的new 方法
newArrayList
newLinkedList
newCopyOnWriteArrayList
newHashSet
newLinkedHashSet
-
#693 NumberUtil 添加一些数字常量
-
#692 NumberUtil 新增比较两个Number 的方法 ,
isEquals(Number, Number)
,isGatherThan(Number, Number)
,isGatherThanOrEquals(Number, Number)
,isLessThan(Number, Number)
,isLessThanOrEquals(Number, Number)
-
#705
DatePattern
新增 . 分隔的时间格式
public static final String DOTS_DATE = "yyyy.MM.dd";
public static final String DOTS_DATE_AND_TIME_WITHOUT_SECOND = "yyyy.MM.dd HH:mm";
public static final String DOTS_DATE_AND_TIME = "yyyy.MM.dd HH:mm:ss";
public static final String DOTS_DATE_AND_TIME_WITH_MILLISECOND = "yyyy.MM.dd HH:mm:ss.SSS";
- #701 新建
DateToStringTransformer
- #702 新建
NumberToStringTransformer
- #675 新建 java.lang.Thread.sleep(long) 工具类
[Update]
- #690 修改 AggregateUtil.groupCount 返回值, 从
Map<String, Map<T, Integer>>
改成Map<String, Map<String, Integer>>
- #688 AggregateUtil.groupCount(Iterable, String[]) 参数 改成动态数组
- #600 修改
CollectionsUtil.remove(Collection<O>, O)
成CollectionsUtil.remove(Collection<O>, O...)
支持动态数组
[Remove]
- #700 remove
com.feilong.core.lang.PartitionThreadEntity.PartitionThreadEntity()
[Fix Bug] 🐛
- none
[javadoc]
- none
[test]
- #710 完善
BeanPredicateUtil
单元测试类 test - #709 新建
BeanPredicate
单元测试类 test - #708 新建
IgnoreCaseEquator
单元测试类 test - #707 新建
RegexGroupNumberComparator
单元测试类 test - #706
BeanPropertyValueChangeClosure
新建单元测试 test - #703 新建
BeanTransformer
单元测试类 test - #704 新建
SimpleClassTransformer
单元测试类 test - #699 URLUtil 完善单元测试 test
[help wanted]
- none
[log]
- none
1.10.6
本次升级共有 20
处变更, 具体参见 1.10.6 milestone
1.10.6 文档地址: http://feilong-core.mydoc.io/
首先预览下,本次发布的核心内容 :
[Feature] 🆕
- #681 添加
ParamUtil.toNaturalOrderingKeyJoinValue(Map<String, String>)
新建 将key和map直接拼接的方法
将 singleValueMap
转成自然排序, 然后将key和value直接拼接成字符串(不使用 = 和& 分隔).
示例:
Map<String, String> map = new HashMap<>();
map.put("service", "create_salesorder");
map.put("_input_charset", "gbk");
map.put("totalActual", "210.00");
map.put("address", "江苏南通市通州区888组888号");
LOGGER.debug(ParamUtil.toNaturalOrderingKeyJoinValue(map));
返回:
_input_charsetgbkaddress江苏南通市通州区888组888号servicecreate_salesordertotalActual210.00
- #673
SortUtil
新增Map<K, V> sortMapByKeyFixOrder(Map<K, V> map,K...keys)
map 按照指定的固定key的顺序排序
按照key 指定名字顺序排序.
注意:
原 map 的顺序不变
示例:
Map<String, Integer> map = new HashMap<>();
map.put("DE", 99);
map.put("L", 3428);
map.put("O", 13);
map.put("UN", 17);
map.put("S", 6);
//L-上市,S-暂停,DE-终止上市,UN-未上市
Map<String, Integer> sortByKeyAsc = sortMapByKeyFixOrder(map, "L", "UN", "DE", "S", "O");
LOGGER.debug(JsonUtil.format(sortByKeyAsc));
返回:
{
"L": 3428,
"UN": 17,
"S": 6,
"DE": 99,
"O": 13
}
- #674
AggregateUtil
新增可以按照 多个属性名字来 groupCount的方法
com.feilong.core.util.AggregateUtil.groupCount(Iterable, String[])
com.feilong.core.util.AggregateUtil.groupCount(Iterable, String[], Predicate)
循环 beanIterable
,只选择符合 includePredicate
的对象,统计 propertyName的值出现的次数.
说明:
返回的LinkedHashMap,key是propertyName名字,子map的key是propertyName对应的值,value是该值出现的次数;
顺序是 beanIterable propertyName的值的顺序
示例:
场景: 统计user list,属性名字是name 的值的数量 以及age值的数量
List<User> list = toList(//
new User("张飞", 20),
new User("关羽", 30),
new User("赵云", 50),
new User("刘备", 40),
new User("刘备", 30),
new User("赵云", 50));
Map<String, Map<Object, Integer>> map = AggregateUtil.groupCount(list, toArray("name", "age"));
LOGGER.debug(JsonUtil.format(map));
返回:
{
"age": {
"20": 1,
"30": 2,
"50": 2,
"40": 1
},
"name": {
"张飞": 1,
"关羽": 1,
"赵云": 2,
"刘备": 2
}
}
- #667
BeanPredicateUtil
新增Predicate<T> equalPredicate(T bean,String...propertyNames)
构造属性与一个指定对象 bean 的一组属性的值 propertyNames 都相等的判断器.
说明:
常用于解析集合,如 select,find, selectRejected, group, groupCount, sum 等方法.
示例:
场景: 在list中查找 名字是 关羽,并且 年龄是30 的user
User guanyu30 = new User("关羽", 30);
List<User> list = toList(//
new User("张飞", 23),
new User("关羽", 24),
new User("刘备", 25),
guanyu30);
Predicate<User> predicate = PredicateUtils
.andPredicate(BeanPredicateUtil.equalPredicate("name", "关羽"), BeanPredicateUtil.equalPredicate("age", 30));
assertEquals(guanyu30, CollectionsUtil.find(list, predicate));
此时你可以优化成:
User guanyu30 = new User("关羽", 30);
List<User> list = toList(//
new User("张飞", 23),
new User("关羽", 24),
new User("刘备", 25),
guanyu30);
assertEquals(guanyu30, find(list, BeanPredicateUtil.equalPredicate(guanyu30, "name", "age")));
- #628
NumberUtil
添加BigDecimal getSubtractValue(Number beSubtractedValue,Number...subtractions)
计算减法的方法
说明:
示例:
NumberUtil.getSubtractValue(0, 2, 3) = -5
NumberUtil.getSubtractValue(0,null) = 0
NumberUtil.getSubtractValue(0, new Integer[5]) = 0
NumberUtil.getSubtractValue(2, 1.1) = 0.9
NumberUtil.getSubtractValue(1000, 99.5, 99.0) = 801.5
NumberUtil.getSubtractValue(1000, 50, null) = 950
NumberUtil.getSubtractValue(-1000, -50, 100) = -1050
NumberUtil.getSubtractValue(null, 5) // NullPointerException
- #686 添加
DateUtil.isToday(Date)
,判断指定的日期 是否是 今天的 方法
判断指定的日期 date,是不是今天的日期.
示例:
DateUtil.isToday(new Date()) = true
// 如果今天 是2017年12月14日
DateUtil.isToday(toDate("2016-06-16 22:59:00", COMMON_DATE_AND_TIME)) = false
- #683 添加
DateExtensionUtil.getTodayStartAndEndPair()
新建获得 今天 开始和结束的时间的方法
获得 今天的开始时间 00:00:00.000 及今天的结束时间 23:59:59.999.
一般用于统计当天数据,between ... and ...
示例:
比如今天的是 2012-10-16 22:18:34
返回: 2012-10-16 00:00:00.000, 2012-10-16 23:59:59.999
-
#684 添加
DateExtensionUtil.getYesterdayStartAndEndPair()
新建获得 昨天 开始和结束的时间的方法 -
#677 添加
DateExtensionUtil.getMonthStartAndEndPair()
新建获得当前月区间的方法 -
#678 添加
DateExtensionUtil.getYearStartAndEndPair()
新建获得当前年区间的方法(第一天0点 到最后一天23:59:59)
[Update]
- #687
DateUtil isEquals(Date date1,Date date2,String datePattern)
,如果 date1 == date2 直接返回true - #669
RegexPattern
移动到feilong-validator
项目 - #621
RegexPattern
配置是否可以提到配置文件,便于商城定制 - #663 更新手机号码正则表达式
- #665
RegexUtil
加上缓存
[Remove]
- #682 删除
DateExtensionUtil.getResetTodayAndTomorrow() getResetYesterdayAndToday
方法 - #592 删除 @deprecated
com.feilong.core.RegexPattern.EMAIL
- #676 删除没有用的
feilong-core-regex.properties
[Fix Bug] 🐛
- none
[javadoc]
- none
[test]
- #672
MessageFormatUtilTest.testFormat()
单元测试报错 bug
[help wanted]
- #670
ThreadUtil
添加 javadoc 关于 callable Javadoc
[log]
- none
1.10.5
本次升级共有 7
处变更, 具体参见 1.10.5 milestone
1.10.5 文档地址: http://feilong-core.mydoc.io/
[Feature] 🆕
- #661 新增
ConvertUtil.toMap(Map<K, V>, Class<J>)
将诸如 Map<String, String>
类型转成 Map<String, Integer>
类型.
说明:
- 适合只是简单的将key value类型转换,而不需要自己再构建
Transformer
,再去调用toMap(Map, Transformer, Transformer)
,简化操作 - 返回的是
LinkedHashMap
,顺序依照入参 inputMap - 返回的是新的map,原来的toMap参数不受影响
- 也支持诸如
Map<String, Integer>
转Map<String, String>
(key和value 使用不同的转换器) - 也支持诸如
Map<String, String>
转Map<String, Integer[]>
(单值转数组) - 也支持诸如
Map<String[], String[]>
转Map<String[], Long[]>
(数组转数组)
示例:
场景1: 将Map<String, String>
转 Map<String, Integer>
类型
Map<String, String> map = toMap("1", "2");
Map<String, Integer> returnMap = toMap(map, Integer.class);
// 输出测试
for (Map.Entry<String, Integer> entry : returnMap.entrySet()){
String key = entry.getKey();
Integer value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:["1"],value:[2]
场景2: Map<String, String>
转 Map<String, Integer[]>
Map<String, String> map = toMap("1", "2,2");
//key和value转成不同的类型
Map<String, Integer[]> returnMap = toMap(map, Integer[].class);
// 输出测试
for (Map.Entry<String, Integer[]> entry : returnMap.entrySet()){
String key = entry.getKey();
Integer[] value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:["1"],value:[[2, 2]]
场景3: Map<String[], String[]> 转 Map<String[], Long[]>
Map<String[], String[]> map = toMap(toArray("1"), toArray("2", "8"));
//key和value转成不同的类型
Map<String[], Long[]> returnMap = toMap(map, Long[].class);
assertThat(returnMap, allOf(hasEntry(toArray("1"), toArray(2L, 8L))));
[Update]
- #657 修改 sonar 扫描出来的问题 The diamond operator
("<>")
should be used 坏味道
[Remove]
- none
[Fix Bug] 🐛
- #643
SortUtil.sortMapByValueDesc(Map<String, Integer>)
会报异常 bug - #659
SortUtil.sortList
报java.lang.IllegalArgumentException: Comparison method violates its general contract!错误 bug thanks @Usain-Zou
[javadoc]
- #660 完善
DateExtensionUtil
注释
[test]
- #653 添加 对
List<Map<String, Object>>
排序的测试方法
[log]
- none
[help wanted]
- #658 整理一个 字符串模板全集的 wiki
1.10.4
本次升级共有 17
处变更, 具体参见 1.10.4 milestone
1.10.4 文档地址: http://feilong-core.mydoc.io/
[Feature] 🆕
- #654 新建
MapUtil.getSubMap(Map<K, T>, Iterable<K>)
获得一个map 中,指定的keys 整理成新的map.
说明:
- 返回的map为 LinkedHashMap,key的顺序 按照参数 keys的顺序
- 如果循环的 key不在map key里面,则忽略该key,并输出debug level log
示例:
Map<String, Integer> map = new HashMap<>();
map.put("a", 3007);
map.put("b", 3001);
map.put("c", 3001);
map.put("d", 3003);
LOGGER.debug(JsonUtil.format(MapUtil.getSubMap(map,toList("a", "c"))));
返回:
{
"a": 3007,
"c": 3001
}
- #655 新建
MapUtil.getSubMapExcludeKeys(Map<K, T>, Iterable<K>)
获得 sub map(排除指定的 excludeKeys).
说明:
- 原 map 不变
- 此方法可以提取Collections.unmodifiableMap(Map)
- 返回值为 LinkedHashMap,key的顺序按照参数 map的顺序
示例:
Map<String, Integer> map = new LinkedHashMap<>();
map.put("a", 3007);
map.put("b", 3001);
map.put("c", 3002);
map.put("g", -1005);
LOGGER.debug(JsonUtil.format(MapUtil.getSubMapExcludeKeys(map, toList("a", "g", "m"))));
返回:
{
"b": 3001,
"c": 3002
}
- #633
ThreadUtil
添加void execute(Runnable runnable,int threadCount)
方法,创建指定数量 threadCount 的线程,并执行.
适用于场景: 模拟个50个线程调用 xxx 方法 的场景 - #652 新建
AnnotationToStringBuilder
- #656 新建
DefaultAnnotationToStringBuilder
[Update]
commons-lang
升级到 3.6 ⬆️- #640 原调用
org.apache.commons.lang3.CharEncoding.UTF_8
改成 StandardCharsets.UTF_8.name() 坏味道 - #639 原调用
SystemUtils.LINE_SEPARATOR
改成java.lang.System.lineSeparator()
坏味道 - #634 如果
RegexUtil.group(String, CharSequence, int)
group <0 抛出异常
[Remove]
- #638 删除
cobertura-maven-plugin
, 添加jacoco-maven-plugin
[Fix Bug] 🐛
- #648 修改
MapUtil.getSubMapExcludeKeys(Map<K, T>, K...)
内部实现,不会改变原来的map bug
[javadoc]
- #649 修改
URIUtil.encode
javadoc
[test]
- #650 添加
EncodeParameterizedTest
- #637 完善
RegexUtilTest
单元测试 - #636 完善
GroupTest
单元测试 - #635 补充
GroupIntTest
单元测试
[log]
1.10.3
本次升级共有 8
处变更, 具体参见 1.10.3 milestone
1.10.3 文档地址: http://feilong-core.mydoc.io/
1.特性 🆕
-
✨ #623 添加
ThreadUtil
, 新增多线程执行方法曾几何时,多线程是JAVA里面很少触碰的技术,而随着技术的发展,对于多线程使用越来越多,在合适的时候合理的使用多线程,对于性能有着质的提高, 但是如果自己从头写,会比较繁琐,那么我们就封装一个吧(这也是feilong的精髓思想之所在)
void execute(List list,int eachSize,Map<String, ?> paramsMap,PartitionRunnableBuilder partitionRunnableBuilder)
给定一个待解析的 list,设定每个线程执行多少条 eachSize,传入一些额外的参数 paramsMap,使用自定义的 partitionRunnableBuilder,自动构造多条线程并运行.
适用场景:
比如同步库存,一次从MQ或者其他接口中得到了5000条数据,如果使用单线程做5000次循环,势必会比较慢,并且影响性能; 如果调用这个方法,传入
eachSize=100
, 那么自动会开启5000/100=50
个线程来跑功能,大大提高同步库存的速度其他的适用场景还有诸如同步商品主档数据,同步订单等等这类每个独立对象之间没有相关联关系的数据,能提高执行速度和效率
具体使用方式,参见文档 http://feilong-core.mydoc.io/?t=192399
2.修改
- #604
ToStringConfig
新增 实例化常量便于调用 - #626
ToStringConfig
实现 tostring 方法 - #625 完善
ToStringConfig
javadoc - #632 完善
PropertyComparator
javadoc - #627 单元测试类包下面的重新命名,不需要类名
3.移除
- none
4.Bug 修复 🐛
1.7.4
修改手机号码正则表达式
1.10.2
本次升级共有13
处变更,具体参见 1.10.2 milestone
1.10.2 文档地址: http://feilong-core.mydoc.io/
1.特性 🆕
- ✨
CollectionsUtil
添加void forEach(final Iterable<O> beanIterable,String propertyName,Object propertyValue)
方法
可以统一修改 集合里面指定属性的值 see #606
对于以下购物车全选的代码:
//找到需要处理的对象list
List<ShoppingCartLineCommand> toDoNeedChangeCheckedCommandList = select(
needChangeCheckedCommandList,
toggleCheckStatusShoppingCartLinePredicateBuilder.build(shoppingCartLineCommandList, checkStatus));
// 将状态修改成对应状态
for (ShoppingCartLineCommand shoppingCartLineCommand : toDoNeedChangeCheckedCommandList){
shoppingCartLineCommand.setSettlementState(1);
}
此时你还可以:
//找到需要处理的对象list
List<ShoppingCartLineCommand> toDoNeedChangeCheckedCommandList = select(
needChangeCheckedCommandList,
toggleCheckStatusShoppingCartLinePredicateBuilder.build(shoppingCartLineCommandList, checkStatus));
// 将状态修改成对应状态
CollectionsUtil.forEach(toDoNeedChangeCheckedCommandList, "settlementState", 1);
- ✨
SortUtil.sortListByPropertyNamesValue
支持倒序排序 fix #608
场景: 将user list 先按照 id desc
再按照 age asc
进行排序
User id12_age18 = new User(12L, 18);
User id1_age8 = new User(1L, 8);
User id2_age30 = new User(2L, 30);
User id2_age2 = new User(2L, 2);
User id2_age36 = new User(2L, 36);
List<User> list = toList(id12_age18, id2_age36, id2_age2, id2_age30, id1_age8);
sortListByPropertyNamesValue(list, "id desc", "age");
assertThat(list, contains(id12_age18, id2_age2, id2_age30, id2_age36, id1_age8));
- ✨
BeanComparatorUtil.propertyComparator(String)
支持倒序排序 #612 - ✨
BeanComparatorUtil.chainedComparator(String...)
支持倒序还是顺序 #609 - ✨ 新建
SortHelper
#611
2.修改
BeanComparatorUtil.chainedComparator(String...)
如果是单值,那么直接使用propertyComparator
返回 #615
3.移除
- none
4.Bug 修复 🐛
1.10.1
本次升级共有4
处变更,具体参见 1.10.1 milestone
1.10.1 文档地址: http://feilong-core.mydoc.io/
1.特性 🆕
-
✨ 添加
MapUtil.get(Map<K, V>, int)
fix #595 -
✨ 添加
List<O> collect(Iterable<I> inputBeanIterable,Class<O> outputListBeanType,String...includePropertyNames)
method fix #559假设你有两个类,
User
,Customer
此时你需要将
List<User>
转换成List<Customer>
List<User> list = toList( new User(23L, "张飞"), new User(24L, "关羽"), new User(25L, "刘备"));
以前你需要如此这般写:
List<Customer> customerList = new ArrayList<>(); for (User user : list){ Customer customer = new Customer(); customer.setId(user.getId()); customer.setName(user.getName()); customerList.add(customer); }
如果属性很多,
书写代码很繁琐
现在你可以这么写:
List<Customer> customerList = CollectionsUtil.collect(list, Customer.class);
一行代码搞定集合转换问题
如果你只想转换id属性,你可以:
List<Customer> customerList = CollectionsUtil.collect(list, Customer.class,"id");
-
✨ 添加
IgnoreCaseEquator
fix #597 -
✨ 添加
BeanPredicateUtil.equalIgnoreCasePredicate(String,String)
fix #598在list中查找 name是
zhangfei
(忽视大小写) 的userList<User> list = toList( new User("zhangfei", 22), new User("zhangFei", 22), new User("Zhangfei", 22), new User((String) null, 22), new User("guanyu", 25), new User("liubei", 30) ); List<User> select = select(list, BeanPredicateUtil.<User> equalIgnoreCasePredicate("name", "zhangfei"));
2.修改
- none
3.移除
- none
4.Bug 修复 🐛
- 🐛 change CollectionsUtil.collect method, 如果入参是null,那么返回null fix #601