Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ma yanling
hutool-5-master
Commits
45cda665
Commit
45cda665
authored
Sep 25, 2024
by
ma yanling
Browse files
project commit
parent
ad2fb30a
Pipeline
#2354
failed with stages
in 0 seconds
Changes
369
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2157 additions
and
0 deletions
+2157
-0
hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java
...ore/src/main/java/cn/hutool/core/collection/ListUtil.java
+683
-0
hutool-core/src/main/java/cn/hutool/core/collection/NodeListIter.java
...src/main/java/cn/hutool/core/collection/NodeListIter.java
+63
-0
hutool-core/src/main/java/cn/hutool/core/collection/Partition.java
...re/src/main/java/cn/hutool/core/collection/Partition.java
+59
-0
hutool-core/src/main/java/cn/hutool/core/collection/PartitionIter.java
...rc/main/java/cn/hutool/core/collection/PartitionIter.java
+59
-0
hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessAvgPartition.java
...a/cn/hutool/core/collection/RandomAccessAvgPartition.java
+32
-0
hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessPartition.java
...java/cn/hutool/core/collection/RandomAccessPartition.java
+27
-0
hutool-core/src/main/java/cn/hutool/core/collection/ResettableIter.java
...c/main/java/cn/hutool/core/collection/ResettableIter.java
+18
-0
hutool-core/src/main/java/cn/hutool/core/collection/RingIndexUtil.java
...rc/main/java/cn/hutool/core/collection/RingIndexUtil.java
+80
-0
hutool-core/src/main/java/cn/hutool/core/collection/SpliteratorUtil.java
.../main/java/cn/hutool/core/collection/SpliteratorUtil.java
+26
-0
hutool-core/src/main/java/cn/hutool/core/collection/TransCollection.java
.../main/java/cn/hutool/core/collection/TransCollection.java
+73
-0
hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java
...re/src/main/java/cn/hutool/core/collection/TransIter.java
+46
-0
hutool-core/src/main/java/cn/hutool/core/collection/TransSpliterator.java
...main/java/cn/hutool/core/collection/TransSpliterator.java
+51
-0
hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java
...src/main/java/cn/hutool/core/collection/UniqueKeySet.java
+177
-0
hutool-core/src/main/java/cn/hutool/core/collection/package-info.java
...src/main/java/cn/hutool/core/collection/package-info.java
+7
-0
hutool-core/src/main/java/cn/hutool/core/comparator/BaseFieldComparator.java
...n/java/cn/hutool/core/comparator/BaseFieldComparator.java
+60
-0
hutool-core/src/main/java/cn/hutool/core/comparator/ComparableComparator.java
.../java/cn/hutool/core/comparator/ComparableComparator.java
+53
-0
hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorChain.java
.../main/java/cn/hutool/core/comparator/ComparatorChain.java
+356
-0
hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorException.java
...n/java/cn/hutool/core/comparator/ComparatorException.java
+32
-0
hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java
.../src/main/java/cn/hutool/core/comparator/CompareUtil.java
+190
-0
hutool-core/src/main/java/cn/hutool/core/comparator/FieldComparator.java
.../main/java/cn/hutool/core/comparator/FieldComparator.java
+65
-0
No files found.
Too many changes to show.
To preserve performance only
369 of 369+
files are displayed.
Plain diff
Email patch
hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.comparator.PinyinComparator
;
import
cn.hutool.core.comparator.PropertyComparator
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.lang.Matcher
;
import
cn.hutool.core.util.ArrayUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.PageUtil
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Enumeration
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.RandomAccess
;
import
java.util.concurrent.CopyOnWriteArrayList
;
import
java.util.function.Consumer
;
/**
* List相关工具类
*
* @author looly
*/
public
class
ListUtil
{
/**
* 新建一个空List
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @return List对象
* @since 4.1.2
*/
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
)
{
return
isLinked
?
new
LinkedList
<>()
:
new
ArrayList
<>();
}
/**
* 新建一个List
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @param values 数组
* @return List对象
* @since 4.1.2
*/
@SafeVarargs
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
,
T
...
values
)
{
if
(
ArrayUtil
.
isEmpty
(
values
))
{
return
list
(
isLinked
);
}
final
List
<
T
>
arrayList
=
isLinked
?
new
LinkedList
<>()
:
new
ArrayList
<>(
values
.
length
);
Collections
.
addAll
(
arrayList
,
values
);
return
arrayList
;
}
/**
* 新建一个List
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @param collection 集合
* @return List对象
* @since 4.1.2
*/
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
,
Collection
<
T
>
collection
)
{
if
(
null
==
collection
)
{
return
list
(
isLinked
);
}
return
isLinked
?
new
LinkedList
<>(
collection
)
:
new
ArrayList
<>(
collection
);
}
/**
* 新建一个List<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @param iterable {@link Iterable}
* @return List对象
* @since 4.1.2
*/
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
,
Iterable
<
T
>
iterable
)
{
if
(
null
==
iterable
)
{
return
list
(
isLinked
);
}
return
list
(
isLinked
,
iterable
.
iterator
());
}
/**
* 新建一个List<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @param iter {@link Iterator}
* @return ArrayList对象
* @since 4.1.2
*/
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
,
Iterator
<
T
>
iter
)
{
final
List
<
T
>
list
=
list
(
isLinked
);
if
(
null
!=
iter
)
{
while
(
iter
.
hasNext
())
{
list
.
add
(
iter
.
next
());
}
}
return
list
;
}
/**
* 新建一个List<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param isLinked 是否新建LinkedList
* @param enumration {@link Enumeration}
* @return ArrayList对象
* @since 3.0.8
*/
public
static
<
T
>
List
<
T
>
list
(
boolean
isLinked
,
Enumeration
<
T
>
enumration
)
{
final
List
<
T
>
list
=
list
(
isLinked
);
if
(
null
!=
enumration
)
{
while
(
enumration
.
hasMoreElements
())
{
list
.
add
(
enumration
.
nextElement
());
}
}
return
list
;
}
/**
* 新建一个ArrayList
*
* @param <T> 集合元素类型
* @param values 数组
* @return ArrayList对象
*/
@SafeVarargs
public
static
<
T
>
ArrayList
<
T
>
toList
(
T
...
values
)
{
return
(
ArrayList
<
T
>)
list
(
false
,
values
);
}
/**
* 新建LinkedList
*
* @param values 数组
* @param <T> 类型
* @return LinkedList
* @since 4.1.2
*/
@SafeVarargs
public
static
<
T
>
LinkedList
<
T
>
toLinkedList
(
T
...
values
)
{
return
(
LinkedList
<
T
>)
list
(
true
,
values
);
}
/**
* 数组转为一个不可变List<br>
* 类似于Java9中的List.of
*
* @param ts 对象
* @param <T> 对象类型
* @return 不可修改List
* @since 5.4.3
*/
@SafeVarargs
public
static
<
T
>
List
<
T
>
of
(
T
...
ts
)
{
if
(
ArrayUtil
.
isEmpty
(
ts
))
{
return
Collections
.
emptyList
();
}
return
Collections
.
unmodifiableList
(
toList
(
ts
));
}
/**
* 新建一个CopyOnWriteArrayList
*
* @param <T> 集合元素类型
* @param collection 集合
* @return {@link CopyOnWriteArrayList}
*/
public
static
<
T
>
CopyOnWriteArrayList
<
T
>
toCopyOnWriteArrayList
(
Collection
<
T
>
collection
)
{
return
(
null
==
collection
)
?
(
new
CopyOnWriteArrayList
<>())
:
(
new
CopyOnWriteArrayList
<>(
collection
));
}
/**
* 新建一个ArrayList
*
* @param <T> 集合元素类型
* @param collection 集合
* @return ArrayList对象
*/
public
static
<
T
>
ArrayList
<
T
>
toList
(
Collection
<
T
>
collection
)
{
return
(
ArrayList
<
T
>)
list
(
false
,
collection
);
}
/**
* 新建一个ArrayList<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param iterable {@link Iterable}
* @return ArrayList对象
* @since 3.1.0
*/
public
static
<
T
>
ArrayList
<
T
>
toList
(
Iterable
<
T
>
iterable
)
{
return
(
ArrayList
<
T
>)
list
(
false
,
iterable
);
}
/**
* 新建一个ArrayList<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param iterator {@link Iterator}
* @return ArrayList对象
* @since 3.0.8
*/
public
static
<
T
>
ArrayList
<
T
>
toList
(
Iterator
<
T
>
iterator
)
{
return
(
ArrayList
<
T
>)
list
(
false
,
iterator
);
}
/**
* 新建一个ArrayList<br>
* 提供的参数为null时返回空{@link ArrayList}
*
* @param <T> 集合元素类型
* @param enumeration {@link Enumeration}
* @return ArrayList对象
* @since 3.0.8
*/
public
static
<
T
>
ArrayList
<
T
>
toList
(
Enumeration
<
T
>
enumeration
)
{
return
(
ArrayList
<
T
>)
list
(
false
,
enumeration
);
}
/**
* 对指定List分页取值
*
* @param <T> 集合元素类型
* @param pageNo 页码,第一页的页码取决于{@link PageUtil#getFirstPageNo()},默认0
* @param pageSize 每页的条目数
* @param list 列表
* @return 分页后的段落内容
* @since 4.1.20
*/
public
static
<
T
>
List
<
T
>
page
(
int
pageNo
,
int
pageSize
,
List
<
T
>
list
)
{
if
(
CollUtil
.
isEmpty
(
list
))
{
return
new
ArrayList
<>(
0
);
}
int
resultSize
=
list
.
size
();
// 每页条目数大于总数直接返回所有
if
(
resultSize
<=
pageSize
)
{
if
(
pageNo
<
(
PageUtil
.
getFirstPageNo
()
+
1
))
{
return
unmodifiable
(
list
);
}
else
{
// 越界直接返回空
return
new
ArrayList
<>(
0
);
}
}
// 相乘可能会导致越界 临时用long
if
(((
long
)
(
pageNo
-
PageUtil
.
getFirstPageNo
())
*
pageSize
)
>
resultSize
)
{
// 越界直接返回空
return
new
ArrayList
<>(
0
);
}
final
int
[]
startEnd
=
PageUtil
.
transToStartEnd
(
pageNo
,
pageSize
);
if
(
startEnd
[
1
]
>
resultSize
)
{
startEnd
[
1
]
=
resultSize
;
if
(
startEnd
[
0
]
>
startEnd
[
1
])
{
return
new
ArrayList
<>(
0
);
}
}
return
sub
(
list
,
startEnd
[
0
],
startEnd
[
1
]);
}
/**
* 对指定List进行分页,逐页返回数据
*
* @param <T> 集合元素类型
* @param list 源数据列表
* @param pageSize 每页的条目数
* @param pageListConsumer 单页数据函数式返回
* @since 5.7.10
*/
public
static
<
T
>
void
page
(
List
<
T
>
list
,
int
pageSize
,
Consumer
<
List
<
T
>>
pageListConsumer
)
{
if
(
CollUtil
.
isEmpty
(
list
)
||
pageSize
<=
0
)
{
return
;
}
final
int
total
=
list
.
size
();
final
int
totalPage
=
PageUtil
.
totalPage
(
total
,
pageSize
);
for
(
int
pageNo
=
PageUtil
.
getFirstPageNo
();
pageNo
<
totalPage
+
PageUtil
.
getFirstPageNo
();
pageNo
++)
{
// 获取当前页在列表中对应的起止序号
final
int
[]
startEnd
=
PageUtil
.
transToStartEnd
(
pageNo
,
pageSize
);
if
(
startEnd
[
1
]
>
total
)
{
startEnd
[
1
]
=
total
;
}
// 返回数据
pageListConsumer
.
accept
(
sub
(
list
,
startEnd
[
0
],
startEnd
[
1
]));
}
}
/**
* 针对List排序,排序会修改原List
*
* @param <T> 元素类型
* @param list 被排序的List
* @param c {@link Comparator}
* @return 原list
* @see Collections#sort(List, Comparator)
*/
public
static
<
T
>
List
<
T
>
sort
(
List
<
T
>
list
,
Comparator
<?
super
T
>
c
)
{
if
(
CollUtil
.
isEmpty
(
list
))
{
return
list
;
}
list
.
sort
(
c
);
return
list
;
}
/**
* 根据Bean的属性排序
*
* @param <T> 元素类型
* @param list List
* @param property 属性名
* @return 排序后的List
* @since 4.0.6
*/
public
static
<
T
>
List
<
T
>
sortByProperty
(
List
<
T
>
list
,
String
property
)
{
return
sort
(
list
,
new
PropertyComparator
<>(
property
));
}
/**
* 根据汉字的拼音顺序排序
*
* @param list List
* @return 排序后的List
* @since 4.0.8
*/
public
static
List
<
String
>
sortByPinyin
(
List
<
String
>
list
)
{
return
sort
(
list
,
new
PinyinComparator
());
}
/**
* 反序给定List,会在原List基础上直接修改
*
* @param <T> 元素类型
* @param list 被反转的List
* @return 反转后的List
* @since 4.0.6
*/
public
static
<
T
>
List
<
T
>
reverse
(
List
<
T
>
list
)
{
Collections
.
reverse
(
list
);
return
list
;
}
/**
* 反序给定List,会创建一个新的List,原List数据不变
*
* @param <T> 元素类型
* @param list 被反转的List
* @return 反转后的List
* @since 4.0.6
*/
public
static
<
T
>
List
<
T
>
reverseNew
(
List
<
T
>
list
)
{
List
<
T
>
list2
=
ObjectUtil
.
clone
(
list
);
if
(
null
==
list2
)
{
// 不支持clone
list2
=
new
ArrayList
<>(
list
);
}
try
{
return
reverse
(
list2
);
}
catch
(
final
UnsupportedOperationException
e
)
{
// 提供的列表不可编辑,新建列表
return
reverse
(
list
(
false
,
list
));
}
}
/**
* 设置或增加元素。当index小于List的长度时,替换指定位置的值,否则在尾部追加
*
* @param <T> 元素类型
* @param list List列表
* @param index 位置
* @param element 新元素
* @return 原List
* @since 4.1.2
*/
public
static
<
T
>
List
<
T
>
setOrAppend
(
List
<
T
>
list
,
int
index
,
T
element
)
{
Assert
.
notNull
(
list
,
"List must be not null !"
);
if
(
index
<
list
.
size
())
{
list
.
set
(
index
,
element
);
}
else
{
list
.
add
(
element
);
}
return
list
;
}
/**
* 在指定位置设置元素。当index小于List的长度时,替换指定位置的值,否则追加{@code null}直到到达index后,设置值
*
* @param <T> 元素类型
* @param list List列表
* @param index 位置
* @param element 新元素
* @return 原List
* @since 5。8.4
*/
public
static
<
T
>
List
<
T
>
setOrPadding
(
List
<
T
>
list
,
int
index
,
T
element
)
{
return
setOrPadding
(
list
,
index
,
element
,
null
);
}
/**
* 在指定位置设置元素。当index小于List的长度时,替换指定位置的值,否则追加{@code paddingElement}直到到达index后,设置值
*
* @param <T> 元素类型
* @param list List列表
* @param index 位置
* @param element 新元素
* @param paddingElement 填充的值
* @return 原List
* @since 5。8.4
*/
public
static
<
T
>
List
<
T
>
setOrPadding
(
List
<
T
>
list
,
int
index
,
T
element
,
T
paddingElement
)
{
Assert
.
notNull
(
list
,
"List must be not null !"
);
final
int
size
=
list
.
size
();
if
(
index
<
size
)
{
list
.
set
(
index
,
element
);
}
else
{
for
(
int
i
=
size
;
i
<
index
;
i
++)
{
list
.
add
(
paddingElement
);
}
list
.
add
(
element
);
}
return
list
;
}
/**
* 截取集合的部分
*
* @param <T> 集合元素类型
* @param list 被截取的数组
* @param start 开始位置(包含)
* @param end 结束位置(不包含)
* @return 截取后的数组,当开始位置超过最大时,返回空的List
*/
public
static
<
T
>
List
<
T
>
sub
(
List
<
T
>
list
,
int
start
,
int
end
)
{
return
sub
(
list
,
start
,
end
,
1
);
}
/**
* 截取集合的部分<br>
* 此方法与{@link List#subList(int, int)} 不同在于子列表是新的副本,操作子列表不会影响原列表。
*
* @param <T> 集合元素类型
* @param list 被截取的数组
* @param start 开始位置(包含)
* @param end 结束位置(不包含)
* @param step 步进
* @return 截取后的数组,当开始位置超过最大时,返回空的List
* @since 4.0.6
*/
public
static
<
T
>
List
<
T
>
sub
(
List
<
T
>
list
,
int
start
,
int
end
,
int
step
)
{
if
(
list
==
null
)
{
return
null
;
}
if
(
list
.
isEmpty
())
{
return
new
ArrayList
<>(
0
);
}
final
int
size
=
list
.
size
();
if
(
start
<
0
)
{
start
+=
size
;
}
if
(
end
<
0
)
{
end
+=
size
;
}
if
(
start
==
size
)
{
return
new
ArrayList
<>(
0
);
}
if
(
start
>
end
)
{
int
tmp
=
start
;
start
=
end
;
end
=
tmp
;
}
if
(
end
>
size
)
{
if
(
start
>=
size
)
{
return
new
ArrayList
<>(
0
);
}
end
=
size
;
}
if
(
step
<
1
)
{
step
=
1
;
}
final
List
<
T
>
result
=
new
ArrayList
<>();
for
(
int
i
=
start
;
i
<
end
;
i
+=
step
)
{
result
.
add
(
list
.
get
(
i
));
}
return
result
;
}
/**
* 获取匹配规则定义中匹配到元素的最后位置<br>
* 此方法对于某些无序集合的位置信息,以转换为数组后的位置为准。
*
* @param <T> 元素类型
* @param list List集合
* @param matcher 匹配器,为空则全部匹配
* @return 最后一个位置
* @since 5.6.6
*/
public
static
<
T
>
int
lastIndexOf
(
List
<
T
>
list
,
Matcher
<
T
>
matcher
)
{
if
(
null
!=
list
)
{
final
int
size
=
list
.
size
();
if
(
size
>
0
)
{
for
(
int
i
=
size
-
1
;
i
>=
0
;
i
--)
{
if
(
null
==
matcher
||
matcher
.
match
(
list
.
get
(
i
)))
{
return
i
;
}
}
}
}
return
-
1
;
}
/**
* 获取匹配规则定义中匹配到元素的所有位置
*
* @param <T> 元素类型
* @param list 列表
* @param matcher 匹配器,为空则全部匹配
* @return 位置数组
* @since 5.2.5
*/
public
static
<
T
>
int
[]
indexOfAll
(
List
<
T
>
list
,
Matcher
<
T
>
matcher
)
{
return
CollUtil
.
indexOfAll
(
list
,
matcher
);
}
/**
* 将对应List转换为不可修改的List
*
* @param list List
* @param <T> 元素类型
* @return 不可修改List
* @since 5.2.6
*/
public
static
<
T
>
List
<
T
>
unmodifiable
(
List
<
T
>
list
)
{
if
(
null
==
list
)
{
return
null
;
}
return
Collections
.
unmodifiableList
(
list
);
}
/**
* 获取一个空List,这个空List不可变
*
* @param <T> 元素类型
* @return 空的List
* @see Collections#emptyList()
* @since 5.2.6
*/
public
static
<
T
>
List
<
T
>
empty
()
{
return
Collections
.
emptyList
();
}
/**
* 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)<br>
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
*
* <p>
* 需要特别注意的是,此方法调用{@link List#subList(int, int)}切分List,
* 此方法返回的是原List的视图,也就是说原List有变更,切分后的结果也会变更。
* </p>
*
* @param <T> 集合元素类型
* @param list 列表,为空时返回{@link #empty()}
* @param size 每个段的长度,当长度超过list长度时,size按照list长度计算,即只返回一个节点
* @return 分段列表
* @since 5.4.5
*/
public
static
<
T
>
List
<
List
<
T
>>
partition
(
List
<
T
>
list
,
int
size
)
{
if
(
CollUtil
.
isEmpty
(
list
))
{
return
empty
();
}
return
(
list
instanceof
RandomAccess
)
?
new
RandomAccessPartition
<>(
list
,
size
)
:
new
Partition
<>(
list
,
size
);
}
/**
* 对集合按照指定长度分段,每一个段为单独的集合,返回这个集合的列表
*
* <p>
* 需要特别注意的是,此方法调用{@link List#subList(int, int)}切分List,
* 此方法返回的是原List的视图,也就是说原List有变更,切分后的结果也会变更。
* </p>
*
* @param <T> 集合元素类型
* @param list 列表,为空时返回{@link #empty()}
* @param size 每个段的长度,当长度超过list长度时,size按照list长度计算,即只返回一个节点
* @return 分段列表
* @see #partition(List, int)
* @since 5.4.5
*/
public
static
<
T
>
List
<
List
<
T
>>
split
(
List
<
T
>
list
,
int
size
)
{
return
partition
(
list
,
size
);
}
/**
* 将集合平均分成多个list,返回这个集合的列表
* <p>例:</p>
* <pre>
* ListUtil.splitAvg(null, 3); // []
* ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 2); // [[1, 2], [3, 4]]
* ListUtil.splitAvg(Arrays.asList(1, 2, 3), 5); // [[1], [2], [3], [], []]
* ListUtil.splitAvg(Arrays.asList(1, 2, 3), 2); // [[1, 2], [3]]
* </pre>
*
* @param <T> 集合元素类型
* @param list 集合
* @param limit 要均分成几个list
* @return 分段列表
* @author lileming
* @since 5.7.10
*/
public
static
<
T
>
List
<
List
<
T
>>
splitAvg
(
List
<
T
>
list
,
int
limit
)
{
if
(
CollUtil
.
isEmpty
(
list
))
{
return
empty
();
}
return
(
list
instanceof
RandomAccess
)
?
new
RandomAccessAvgPartition
<>(
list
,
limit
)
:
new
AvgPartition
<>(
list
,
limit
);
}
/**
* 将指定元素交换到指定索引位置,其他元素的索引值不变<br>
* 交换会修改原List<br>
* 如果集合中有多个相同元素,只交换第一个找到的元素
*
* @param <T> 元素类型
* @param list 列表
* @param element 需交换元素
* @param targetIndex 目标索引
* @since 5.7.13
*/
public
static
<
T
>
void
swapTo
(
List
<
T
>
list
,
T
element
,
Integer
targetIndex
)
{
if
(
CollUtil
.
isNotEmpty
(
list
))
{
final
int
index
=
list
.
indexOf
(
element
);
if
(
index
>=
0
)
{
Collections
.
swap
(
list
,
index
,
targetIndex
);
}
}
}
/**
* 将指定元素交换到指定元素位置,其他元素的索引值不变<br>
* 交换会修改原List<br>
* 如果集合中有多个相同元素,只交换第一个找到的元素
*
* @param <T> 元素类型
* @param list 列表
* @param element 需交换元素
* @param targetElement 目标元素
*/
public
static
<
T
>
void
swapElement
(
List
<
T
>
list
,
T
element
,
T
targetElement
)
{
if
(
CollUtil
.
isNotEmpty
(
list
))
{
final
int
targetIndex
=
list
.
indexOf
(
targetElement
);
if
(
targetIndex
>=
0
)
{
swapTo
(
list
,
element
,
targetIndex
);
}
}
}
}
hutool-core/src/main/java/cn/hutool/core/collection/NodeListIter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.lang.Assert
;
import
org.w3c.dom.Node
;
import
org.w3c.dom.NodeList
;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
/**
* 包装 {@link NodeList} 的{@link Iterator}
* <p>
* 此 iterator 不支持 {@link #remove()} 方法。
*
* @author apache commons,looly
* @see NodeList
* @since 5.8.0
*/
public
class
NodeListIter
implements
ResettableIter
<
Node
>
{
private
final
NodeList
nodeList
;
/**
* 当前位置索引
*/
private
int
index
=
0
;
/**
* 构造, 根据给定{@link NodeList} 创建{@code NodeListIterator}
*
* @param nodeList {@link NodeList},非空
*/
public
NodeListIter
(
final
NodeList
nodeList
)
{
this
.
nodeList
=
Assert
.
notNull
(
nodeList
,
"NodeList must not be null."
);
}
@Override
public
boolean
hasNext
()
{
return
nodeList
!=
null
&&
index
<
nodeList
.
getLength
();
}
@Override
public
Node
next
()
{
if
(
nodeList
!=
null
&&
index
<
nodeList
.
getLength
())
{
return
nodeList
.
item
(
index
++);
}
throw
new
NoSuchElementException
(
"underlying nodeList has no more elements"
);
}
/**
* Throws {@link UnsupportedOperationException}.
*
* @throws UnsupportedOperationException always
*/
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
(
"remove() method not supported for a NodeListIterator."
);
}
@Override
public
void
reset
()
{
this
.
index
=
0
;
}
}
hutool-core/src/main/java/cn/hutool/core/collection/Partition.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.lang.Assert
;
import
java.util.AbstractList
;
import
java.util.List
;
/**
* 列表分区或分段<br>
* 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)<br>
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
* 参考:Guava的Lists#Partition
*
* @param <T> 元素类型
* @author looly, guava
* @since 5.7.10
*/
public
class
Partition
<
T
>
extends
AbstractList
<
List
<
T
>>
{
protected
final
List
<
T
>
list
;
protected
final
int
size
;
/**
* 列表分区
*
* @param list 被分区的列表,非空
* @param size 每个分区的长度,必须>0
*/
public
Partition
(
List
<
T
>
list
,
int
size
)
{
this
.
list
=
Assert
.
notNull
(
list
);
this
.
size
=
Math
.
min
(
list
.
size
(),
size
);
}
@Override
public
List
<
T
>
get
(
int
index
)
{
final
int
start
=
index
*
size
;
final
int
end
=
Math
.
min
(
start
+
size
,
list
.
size
());
return
list
.
subList
(
start
,
end
);
}
@Override
public
int
size
()
{
// 此处采用动态计算,以应对list变
final
int
size
=
this
.
size
;
if
(
0
==
size
){
return
0
;
}
final
int
total
=
list
.
size
();
// 类似于判断余数,当总数非整份size时,多余的数>=1,则相当于被除数多一个size,做到+1目的
// 类似于:if(total % size > 0){length += 1;}
return
(
total
+
size
-
1
)
/
size
;
}
@Override
public
boolean
isEmpty
()
{
return
list
.
isEmpty
();
}
}
hutool-core/src/main/java/cn/hutool/core/collection/PartitionIter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* 分批迭代工具,可以分批处理数据
* <ol>
* <li>比如调用其他客户的接口,传入的入参有限,需要分批</li>
* <li>比如mysql/oracle用in语句查询,超过1000可以分批</li>
* <li>比如数据库取出游标,可以把游标里的数据一批一批处理</li>
* </ol>
*
* @param <T> 字段类型
* @author qiqi.chen
* @since 5.7.10
*/
public
class
PartitionIter
<
T
>
implements
IterableIter
<
List
<
T
>>,
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 被分批的迭代器
*/
protected
final
Iterator
<
T
>
iterator
;
/**
* 实际每批大小
*/
protected
final
int
partitionSize
;
/**
* 创建分组对象
*
* @param iterator 迭代器
* @param partitionSize 每批大小,最后一批不满一批算一批
*/
public
PartitionIter
(
Iterator
<
T
>
iterator
,
int
partitionSize
)
{
this
.
iterator
=
iterator
;
this
.
partitionSize
=
partitionSize
;
}
@Override
public
boolean
hasNext
()
{
return
this
.
iterator
.
hasNext
();
}
@Override
public
List
<
T
>
next
()
{
final
List
<
T
>
list
=
new
ArrayList
<>(
this
.
partitionSize
);
for
(
int
i
=
0
;
i
<
this
.
partitionSize
;
i
++)
{
if
(
false
==
iterator
.
hasNext
())
{
break
;
}
list
.
add
(
iterator
.
next
());
}
return
list
;
}
}
hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessAvgPartition.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.util.List
;
import
java.util.RandomAccess
;
/**
* 列表分区或分段(可随机访问列表)<br>
* 通过传入分区个数,将指定列表分区为不同的块,每块区域的长度均匀分布(个数差不超过1)<br>
* <pre>
* [1,2,3,4] -》 [1,2], [3, 4]
* [1,2,3,4] -》 [1,2], [3], [4]
* [1,2,3,4] -》 [1], [2], [3], [4]
* [1,2,3,4] -》 [1], [2], [3], [4], []
* </pre>
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
*
* @param <T> 元素类型
* @author looly
* @since 5.7.10
*/
public
class
RandomAccessAvgPartition
<
T
>
extends
AvgPartition
<
T
>
implements
RandomAccess
{
/**
* 列表分区
*
* @param list 被分区的列表
* @param limit 分区个数
*/
public
RandomAccessAvgPartition
(
List
<
T
>
list
,
int
limit
)
{
super
(
list
,
limit
);
}
}
hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessPartition.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.util.List
;
import
java.util.RandomAccess
;
/**
* 列表分区或分段(可随机访问列表)<br>
* 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)<br>
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
* 参考:Guava的Lists#RandomAccessPartition
*
* @param <T> 元素类型
* @author looly, guava
* @since 5.7.10
*/
public
class
RandomAccessPartition
<
T
>
extends
Partition
<
T
>
implements
RandomAccess
{
/**
* 构造
*
* @param list 被分区的列表,必须实现{@link RandomAccess}
* @param size 每个分区的长度
*/
public
RandomAccessPartition
(
List
<
T
>
list
,
int
size
)
{
super
(
list
,
size
);
}
}
hutool-core/src/main/java/cn/hutool/core/collection/ResettableIter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.util.Iterator
;
/**
* 支持重置的{@link Iterator} 接口<br>
* 通过实现{@link #reset()},重置此{@link Iterator}后可实现复用重新遍历
*
* @param <E> 元素类型
* @since 5.8.0
*/
public
interface
ResettableIter
<
E
>
extends
Iterator
<
E
>
{
/**
* 重置,重置后可重新遍历
*/
void
reset
();
}
hutool-core/src/main/java/cn/hutool/core/collection/RingIndexUtil.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.lang.Assert
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* 集合索引环形获取工具类
*
* @author ZhouChuGang
* @since 5.7.15
*/
public
class
RingIndexUtil
{
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param object 集合
* <ul>
* <li>Collection - the collection size
* <li>Map - the map size
* <li>Array - the array size
* <li>Iterator - the number of elements remaining in the iterator
* <li>Enumeration - the number of elements remaining in the enumeration
* </ul>
* @param atomicInteger 原子操作类
* @return 索引位置
*/
public
static
int
ringNextIntByObj
(
Object
object
,
AtomicInteger
atomicInteger
)
{
Assert
.
notNull
(
object
);
int
modulo
=
CollUtil
.
size
(
object
);
return
ringNextInt
(
modulo
,
atomicInteger
);
}
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param modulo 回环周期值
* @param atomicInteger 原子操作类
* @return 索引位置
*/
public
static
int
ringNextInt
(
int
modulo
,
AtomicInteger
atomicInteger
)
{
Assert
.
notNull
(
atomicInteger
);
Assert
.
isTrue
(
modulo
>
0
);
if
(
modulo
<=
1
)
{
return
0
;
}
for
(;
;
)
{
int
current
=
atomicInteger
.
get
();
int
next
=
(
current
+
1
)
%
modulo
;
if
(
atomicInteger
.
compareAndSet
(
current
,
next
))
{
return
next
;
}
}
}
/**
* 通过cas操作 实现对指定值内的回环累加<br>
* 此方法一般用于大量数据完成回环累加(如数据库中的值大于int最大值)
*
* @param modulo 回环周期值
* @param atomicLong 原子操作类
* @return 索引位置
*/
public
static
long
ringNextLong
(
long
modulo
,
AtomicLong
atomicLong
)
{
Assert
.
notNull
(
atomicLong
);
Assert
.
isTrue
(
modulo
>
0
);
if
(
modulo
<=
1
)
{
return
0
;
}
for
(;
;
)
{
long
current
=
atomicLong
.
get
();
long
next
=
(
current
+
1
)
%
modulo
;
if
(
atomicLong
.
compareAndSet
(
current
,
next
))
{
return
next
;
}
}
}
}
hutool-core/src/main/java/cn/hutool/core/collection/SpliteratorUtil.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.util.Spliterator
;
import
java.util.function.Function
;
/**
* {@link Spliterator}相关工具类
*
* @author looly
* @since 5.4.3
*/
public
class
SpliteratorUtil
{
/**
* 使用给定的转换函数,转换源{@link Spliterator}为新类型的{@link Spliterator}
*
* @param <F> 源元素类型
* @param <T> 目标元素类型
* @param fromSpliterator 源{@link Spliterator}
* @param function 转换函数
* @return 新类型的{@link Spliterator}
*/
public
static
<
F
,
T
>
Spliterator
<
T
>
trans
(
Spliterator
<
F
>
fromSpliterator
,
Function
<?
super
F
,
?
extends
T
>
function
)
{
return
new
TransSpliterator
<>(
fromSpliterator
,
function
);
}
}
hutool-core/src/main/java/cn/hutool/core/collection/TransCollection.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.lang.Assert
;
import
java.util.AbstractCollection
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.Spliterator
;
import
java.util.function.Consumer
;
import
java.util.function.Function
;
import
java.util.function.Predicate
;
/**
* 使用给定的转换函数,转换源集合为新类型的集合
*
* @param <F> 源元素类型
* @param <T> 目标元素类型
* @author looly
* @since 5.4.3
*/
public
class
TransCollection
<
F
,
T
>
extends
AbstractCollection
<
T
>
{
private
final
Collection
<
F
>
fromCollection
;
private
final
Function
<?
super
F
,
?
extends
T
>
function
;
/**
* 构造
*
* @param fromCollection 源集合
* @param function 转换函数
*/
public
TransCollection
(
Collection
<
F
>
fromCollection
,
Function
<?
super
F
,
?
extends
T
>
function
)
{
this
.
fromCollection
=
Assert
.
notNull
(
fromCollection
);
this
.
function
=
Assert
.
notNull
(
function
);
}
@Override
public
Iterator
<
T
>
iterator
()
{
return
IterUtil
.
trans
(
fromCollection
.
iterator
(),
function
);
}
@Override
public
void
clear
()
{
fromCollection
.
clear
();
}
@Override
public
boolean
isEmpty
()
{
return
fromCollection
.
isEmpty
();
}
@Override
public
void
forEach
(
Consumer
<?
super
T
>
action
)
{
Assert
.
notNull
(
action
);
fromCollection
.
forEach
((
f
)
->
action
.
accept
(
function
.
apply
(
f
)));
}
@Override
public
boolean
removeIf
(
Predicate
<?
super
T
>
filter
)
{
Assert
.
notNull
(
filter
);
return
fromCollection
.
removeIf
(
element
->
filter
.
test
(
function
.
apply
(
element
)));
}
@Override
public
Spliterator
<
T
>
spliterator
()
{
return
SpliteratorUtil
.
trans
(
fromCollection
.
spliterator
(),
function
);
}
@Override
public
int
size
()
{
return
fromCollection
.
size
();
}
}
\ No newline at end of file
hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.lang.Assert
;
import
java.util.Iterator
;
import
java.util.function.Function
;
/**
* 使用给定的转换函数,转换源{@link Iterator}为新类型的{@link Iterator}
*
* @param <F> 源元素类型
* @param <T> 目标元素类型
* @author looly
* @since 5.4.3
*/
public
class
TransIter
<
F
,
T
>
implements
Iterator
<
T
>
{
private
final
Iterator
<?
extends
F
>
backingIterator
;
private
final
Function
<?
super
F
,
?
extends
T
>
func
;
/**
* 构造
*
* @param backingIterator 源{@link Iterator}
* @param func 转换函数
*/
public
TransIter
(
final
Iterator
<?
extends
F
>
backingIterator
,
final
Function
<?
super
F
,
?
extends
T
>
func
)
{
this
.
backingIterator
=
Assert
.
notNull
(
backingIterator
);
this
.
func
=
Assert
.
notNull
(
func
);
}
@Override
public
final
boolean
hasNext
()
{
return
backingIterator
.
hasNext
();
}
@Override
public
final
T
next
()
{
return
func
.
apply
(
backingIterator
.
next
());
}
@Override
public
final
void
remove
()
{
backingIterator
.
remove
();
}
}
hutool-core/src/main/java/cn/hutool/core/collection/TransSpliterator.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
java.util.Spliterator
;
import
java.util.function.Consumer
;
import
java.util.function.Function
;
/**
* 使用给定的转换函数,转换源{@link Spliterator}为新类型的{@link Spliterator}
*
* @param <F> 源元素类型
* @param <T> 目标元素类型
* @author looly
* @since 5.4.3
*/
public
class
TransSpliterator
<
F
,
T
>
implements
Spliterator
<
T
>
{
private
final
Spliterator
<
F
>
fromSpliterator
;
private
final
Function
<?
super
F
,
?
extends
T
>
function
;
public
TransSpliterator
(
Spliterator
<
F
>
fromSpliterator
,
Function
<?
super
F
,
?
extends
T
>
function
)
{
this
.
fromSpliterator
=
fromSpliterator
;
this
.
function
=
function
;
}
@Override
public
boolean
tryAdvance
(
Consumer
<?
super
T
>
action
)
{
return
fromSpliterator
.
tryAdvance
(
fromElement
->
action
.
accept
(
function
.
apply
(
fromElement
)));
}
@Override
public
void
forEachRemaining
(
Consumer
<?
super
T
>
action
)
{
fromSpliterator
.
forEachRemaining
(
fromElement
->
action
.
accept
(
function
.
apply
(
fromElement
)));
}
@Override
public
Spliterator
<
T
>
trySplit
()
{
Spliterator
<
F
>
fromSplit
=
fromSpliterator
.
trySplit
();
return
(
fromSplit
!=
null
)
?
new
TransSpliterator
<>(
fromSplit
,
function
)
:
null
;
}
@Override
public
long
estimateSize
()
{
return
fromSpliterator
.
estimateSize
();
}
@Override
public
int
characteristics
()
{
return
fromSpliterator
.
characteristics
()
&
~(
Spliterator
.
DISTINCT
|
Spliterator
.
NONNULL
|
Spliterator
.
SORTED
);
}
}
hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.collection
;
import
cn.hutool.core.map.MapBuilder
;
import
cn.hutool.core.util.ObjectUtil
;
import
java.io.Serializable
;
import
java.util.AbstractSet
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.function.Function
;
/**
* 唯一键的Set<br>
* 通过自定义唯一键,通过{@link #uniqueGenerator}生成节点对象对应的键作为Map的key,确定唯一<br>
* 此Set与HashSet不同的是,HashSet依赖于{@link Object#equals(Object)}确定唯一<br>
* 但是很多时候我们无法对对象进行修改,此时在外部定义一个唯一规则,即可完成去重。
* <pre>
* {@code Set<UniqueTestBean> set = new UniqueKeySet<>(UniqueTestBean::getId);}
* </pre>
*
* @param <K> 唯一键类型
* @param <V> 值对象
* @author looly
* @since 5.7.23
*/
public
class
UniqueKeySet
<
K
,
V
>
extends
AbstractSet
<
V
>
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
Map
<
K
,
V
>
map
;
private
final
Function
<
V
,
K
>
uniqueGenerator
;
//region 构造
/**
* 构造
*
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
*/
public
UniqueKeySet
(
Function
<
V
,
K
>
uniqueGenerator
)
{
this
(
false
,
uniqueGenerator
);
}
/**
* 构造
*
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
* @param c 初始化加入的集合
* @since 5.8.0
*/
public
UniqueKeySet
(
Function
<
V
,
K
>
uniqueGenerator
,
Collection
<?
extends
V
>
c
)
{
this
(
false
,
uniqueGenerator
,
c
);
}
/**
* 构造
*
* @param isLinked 是否保持加入顺序
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
*/
public
UniqueKeySet
(
boolean
isLinked
,
Function
<
V
,
K
>
uniqueGenerator
)
{
this
(
MapBuilder
.
create
(
isLinked
),
uniqueGenerator
);
}
/**
* 构造
*
* @param isLinked 是否保持加入顺序
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
* @param c 初始化加入的集合
* @since 5.8.0
*/
public
UniqueKeySet
(
boolean
isLinked
,
Function
<
V
,
K
>
uniqueGenerator
,
Collection
<?
extends
V
>
c
)
{
this
(
isLinked
,
uniqueGenerator
);
addAll
(
c
);
}
/**
* 构造
*
* @param initialCapacity 初始容量
* @param loadFactor 增长因子
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
*/
public
UniqueKeySet
(
int
initialCapacity
,
float
loadFactor
,
Function
<
V
,
K
>
uniqueGenerator
)
{
this
(
MapBuilder
.
create
(
new
HashMap
<>(
initialCapacity
,
loadFactor
)),
uniqueGenerator
);
}
/**
* 构造
*
* @param builder 初始Map,定义了Map类型
* @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键
*/
public
UniqueKeySet
(
MapBuilder
<
K
,
V
>
builder
,
Function
<
V
,
K
>
uniqueGenerator
)
{
this
.
map
=
builder
.
build
();
this
.
uniqueGenerator
=
uniqueGenerator
;
}
//endregion
@Override
public
Iterator
<
V
>
iterator
()
{
return
map
.
values
().
iterator
();
}
@Override
public
int
size
()
{
return
map
.
size
();
}
@Override
public
boolean
isEmpty
()
{
return
map
.
isEmpty
();
}
@Override
public
boolean
contains
(
Object
o
)
{
//noinspection unchecked
return
map
.
containsKey
(
this
.
uniqueGenerator
.
apply
((
V
)
o
));
}
@Override
public
boolean
add
(
V
v
)
{
return
null
==
map
.
put
(
this
.
uniqueGenerator
.
apply
(
v
),
v
);
}
/**
* 加入值,如果值已经存在,则忽略之
*
* @param v 值
* @return 是否成功加入
*/
public
boolean
addIfAbsent
(
V
v
)
{
return
null
==
map
.
putIfAbsent
(
this
.
uniqueGenerator
.
apply
(
v
),
v
);
}
/**
* 加入集合中所有的值,如果值已经存在,则忽略之
*
* @param c 集合
* @return 是否有一个或多个被加入成功
*/
public
boolean
addAllIfAbsent
(
Collection
<?
extends
V
>
c
)
{
boolean
modified
=
false
;
for
(
V
v
:
c
)
if
(
addIfAbsent
(
v
))
{
modified
=
true
;
}
return
modified
;
}
@Override
public
boolean
remove
(
Object
o
)
{
//noinspection unchecked
return
null
!=
map
.
remove
(
this
.
uniqueGenerator
.
apply
((
V
)
o
));
}
@Override
public
void
clear
()
{
map
.
clear
();
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
UniqueKeySet
<
K
,
V
>
clone
()
{
try
{
UniqueKeySet
<
K
,
V
>
newSet
=
(
UniqueKeySet
<
K
,
V
>)
super
.
clone
();
newSet
.
map
=
ObjectUtil
.
clone
(
this
.
map
);
return
newSet
;
}
catch
(
CloneNotSupportedException
e
)
{
throw
new
InternalError
(
e
);
}
}
}
hutool-core/src/main/java/cn/hutool/core/collection/package-info.java
0 → 100644
View file @
45cda665
/**
* 集合以及Iterator封装,包括集合工具CollUtil,Iterator和Iterable工具IterUtil
*
* @author looly
*
*/
package
cn.hutool.core.collection
;
\ No newline at end of file
hutool-core/src/main/java/cn/hutool/core/comparator/BaseFieldComparator.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ReflectUtil
;
import
java.io.Serializable
;
import
java.lang.reflect.Field
;
import
java.util.Comparator
;
/**
* Bean字段排序器<br>
* 参阅feilong-core中的PropertyComparator
*
* @param <T> 被比较的Bean
* @author jiangzeyin
* @deprecated 此类不再需要,使用FuncComparator代替更加灵活
*/
@Deprecated
public
abstract
class
BaseFieldComparator
<
T
>
implements
Comparator
<
T
>,
Serializable
{
private
static
final
long
serialVersionUID
=
-
3482464782340308755L
;
/**
* 比较两个对象的同一个字段值
*
* @param o1 对象1
* @param o2 对象2
* @param field 字段
* @return 比较结果
*/
protected
int
compareItem
(
T
o1
,
T
o2
,
Field
field
)
{
if
(
o1
==
o2
)
{
return
0
;
}
else
if
(
null
==
o1
)
{
// null 排在后面
return
1
;
}
else
if
(
null
==
o2
)
{
return
-
1
;
}
Comparable
<?>
v1
;
Comparable
<?>
v2
;
try
{
v1
=
(
Comparable
<?>)
ReflectUtil
.
getFieldValue
(
o1
,
field
);
v2
=
(
Comparable
<?>)
ReflectUtil
.
getFieldValue
(
o2
,
field
);
}
catch
(
Exception
e
)
{
throw
new
ComparatorException
(
e
);
}
return
compare
(
o1
,
o2
,
v1
,
v2
);
}
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
private
int
compare
(
T
o1
,
T
o2
,
Comparable
fieldValue1
,
Comparable
fieldValue2
)
{
int
result
=
ObjectUtil
.
compare
(
fieldValue1
,
fieldValue2
);
if
(
0
==
result
)
{
//避免TreeSet / TreeMap 过滤掉排序字段相同但是对象不相同的情况
result
=
CompareUtil
.
compare
(
o1
,
o2
,
true
);
}
return
result
;
}
}
hutool-core/src/main/java/cn/hutool/core/comparator/ComparableComparator.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
java.io.Serializable
;
import
java.util.Comparator
;
/**
* 针对 {@link Comparable}对象的默认比较器
*
* @param <E> 比较对象类型
* @author Looly
* @since 3.0.7
*/
public
class
ComparableComparator
<
E
extends
Comparable
<?
super
E
>>
implements
Comparator
<
E
>,
Serializable
{
private
static
final
long
serialVersionUID
=
3020871676147289162L
;
/** 单例 */
@SuppressWarnings
(
"rawtypes"
)
public
static
final
ComparableComparator
INSTANCE
=
new
ComparableComparator
<>();
/**
* 构造
*/
public
ComparableComparator
()
{
}
/**
* 比较两个{@link Comparable}对象
*
* <pre>
* obj1.compareTo(obj2)
* </pre>
*
* @param obj1 被比较的第一个对象
* @param obj2 the second object to compare
* @return obj1小返回负数,大返回正数,否则返回0
* @throws NullPointerException obj1为{@code null}或者比较中抛出空指针异常
*/
@Override
public
int
compare
(
final
E
obj1
,
final
E
obj2
)
{
return
obj1
.
compareTo
(
obj2
);
}
@Override
public
int
hashCode
()
{
return
"ComparableComparator"
.
hashCode
();
}
@Override
public
boolean
equals
(
final
Object
object
)
{
return
this
==
object
||
null
!=
object
&&
object
.
getClass
().
equals
(
this
.
getClass
());
}
}
\ No newline at end of file
hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorChain.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
cn.hutool.core.lang.Chain
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.BitSet
;
import
java.util.Comparator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Objects
;
/**
* 比较器链。此链包装了多个比较器,最终比较结果按照比较器顺序综合多个比较器结果。<br>
* 按照比较器链的顺序分别比较,如果比较出相等则转向下一个比较器,否则直接返回<br>
* 此类copy from Apache-commons-collections
*
* @author looly
* @since 3.0.7
*/
public
class
ComparatorChain
<
E
>
implements
Chain
<
Comparator
<
E
>,
ComparatorChain
<
E
>>,
Comparator
<
E
>,
Serializable
{
private
static
final
long
serialVersionUID
=
-
2426725788913962429L
;
/**
* 比较器链.
*/
private
final
List
<
Comparator
<
E
>>
chain
;
/**
* 对应比较器位置是否反序.
*/
private
final
BitSet
orderingBits
;
/**
* 比较器是否被锁定。锁定的比较器链不能再添加新的比较器。比较器会在开始比较时开始加锁。
*/
private
boolean
lock
=
false
;
//------------------------------------------------------------------------------------- Static method start
/**
* 构建 {@link ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparator 比较器
* @return {@link ComparatorChain}
* @since 5.4.3
*/
public
static
<
E
>
ComparatorChain
<
E
>
of
(
Comparator
<
E
>
comparator
)
{
return
of
(
comparator
,
false
);
}
/**
* 构建 {@link ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparator 比较器
* @param reverse 是否反向
* @return {@link ComparatorChain}
* @since 5.4.3
*/
public
static
<
E
>
ComparatorChain
<
E
>
of
(
Comparator
<
E
>
comparator
,
boolean
reverse
)
{
return
new
ComparatorChain
<>(
comparator
,
reverse
);
}
/**
* 构建 {@link ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器数组
* @return {@link ComparatorChain}
* @since 5.4.3
*/
@SafeVarargs
public
static
<
E
>
ComparatorChain
<
E
>
of
(
Comparator
<
E
>...
comparators
)
{
return
of
(
Arrays
.
asList
(
comparators
));
}
/**
* 构建 {@link ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器列表
* @return {@link ComparatorChain}
* @since 5.4.3
*/
public
static
<
E
>
ComparatorChain
<
E
>
of
(
List
<
Comparator
<
E
>>
comparators
)
{
return
new
ComparatorChain
<>(
comparators
);
}
/**
* 构建 {@link ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器列表
* @param bits {@link Comparator} 列表对应的排序boolean值,true表示正序,false反序
* @return {@link ComparatorChain}
* @since 5.4.3
*/
public
static
<
E
>
ComparatorChain
<
E
>
of
(
List
<
Comparator
<
E
>>
comparators
,
BitSet
bits
)
{
return
new
ComparatorChain
<>(
comparators
,
bits
);
}
//------------------------------------------------------------------------------------- Static method start
/**
* 构造空的比较器链,必须至少有一个比较器,否则会在compare时抛出{@link UnsupportedOperationException}
*/
public
ComparatorChain
()
{
this
(
new
ArrayList
<>(),
new
BitSet
());
}
/**
* 构造,初始化单一比较器。比较器为正序
*
* @param comparator 在比较器链中的第一个比较器
*/
public
ComparatorChain
(
final
Comparator
<
E
>
comparator
)
{
this
(
comparator
,
false
);
}
/**
* 构造,初始化单一比较器。自定义正序还是反序
*
* @param comparator 在比较器链中的第一个比较器
* @param reverse 是否反序,true表示反序,false正序
*/
public
ComparatorChain
(
final
Comparator
<
E
>
comparator
,
final
boolean
reverse
)
{
chain
=
new
ArrayList
<>(
1
);
chain
.
add
(
comparator
);
orderingBits
=
new
BitSet
(
1
);
if
(
reverse
==
true
)
{
orderingBits
.
set
(
0
);
}
}
/**
* 构造,使用已有的比较器列表
*
* @param list 比较器列表
* @see #ComparatorChain(List, BitSet)
*/
public
ComparatorChain
(
final
List
<
Comparator
<
E
>>
list
)
{
this
(
list
,
new
BitSet
(
list
.
size
()));
}
/**
* 构造,使用已有的比较器列表和对应的BitSet<br>
* BitSet中的boolean值需与list中的{@link Comparator}一一对应,true表示正序,false反序
*
* @param list {@link Comparator} 列表
* @param bits {@link Comparator} 列表对应的排序boolean值,true表示正序,false反序
*/
public
ComparatorChain
(
final
List
<
Comparator
<
E
>>
list
,
final
BitSet
bits
)
{
chain
=
list
;
orderingBits
=
bits
;
}
/**
* 在链的尾部添加比较器,使用正向排序
*
* @param comparator {@link Comparator} 比较器,正向
* @return this
*/
public
ComparatorChain
<
E
>
addComparator
(
final
Comparator
<
E
>
comparator
)
{
return
addComparator
(
comparator
,
false
);
}
/**
* 在链的尾部添加比较器,使用给定排序方式
*
* @param comparator {@link Comparator} 比较器
* @param reverse 是否反序,true表示正序,false反序
* @return this
*/
public
ComparatorChain
<
E
>
addComparator
(
final
Comparator
<
E
>
comparator
,
final
boolean
reverse
)
{
checkLocked
();
chain
.
add
(
comparator
);
if
(
reverse
==
true
)
{
orderingBits
.
set
(
chain
.
size
()
-
1
);
}
return
this
;
}
/**
* 替换指定位置的比较器,保持原排序方式
*
* @param index 位置
* @param comparator {@link Comparator}
* @return this
* @throws IndexOutOfBoundsException if index < 0 or index >= size()
*/
public
ComparatorChain
<
E
>
setComparator
(
final
int
index
,
final
Comparator
<
E
>
comparator
)
throws
IndexOutOfBoundsException
{
return
setComparator
(
index
,
comparator
,
false
);
}
/**
* 替换指定位置的比较器,替换指定排序方式
*
* @param index 位置
* @param comparator {@link Comparator}
* @param reverse 是否反序,true表示正序,false反序
* @return this
*/
public
ComparatorChain
<
E
>
setComparator
(
final
int
index
,
final
Comparator
<
E
>
comparator
,
final
boolean
reverse
)
{
checkLocked
();
chain
.
set
(
index
,
comparator
);
if
(
reverse
==
true
)
{
orderingBits
.
set
(
index
);
}
else
{
orderingBits
.
clear
(
index
);
}
return
this
;
}
/**
* 更改指定位置的排序方式为正序
*
* @param index 位置
* @return this
*/
public
ComparatorChain
<
E
>
setForwardSort
(
final
int
index
)
{
checkLocked
();
orderingBits
.
clear
(
index
);
return
this
;
}
/**
* 更改指定位置的排序方式为反序
*
* @param index 位置
* @return this
*/
public
ComparatorChain
<
E
>
setReverseSort
(
final
int
index
)
{
checkLocked
();
orderingBits
.
set
(
index
);
return
this
;
}
/**
* 比较器链中比较器个数
*
* @return Comparator count
*/
public
int
size
()
{
return
chain
.
size
();
}
/**
* 是否已经被锁定。当开始比较时(调用compare方法)此值为true
*
* @return true = ComparatorChain cannot be modified; false = ComparatorChain can still be modified.
*/
public
boolean
isLocked
()
{
return
lock
;
}
@Override
public
Iterator
<
Comparator
<
E
>>
iterator
()
{
return
this
.
chain
.
iterator
();
}
@Override
public
ComparatorChain
<
E
>
addChain
(
Comparator
<
E
>
element
)
{
return
this
.
addComparator
(
element
);
}
/**
* 执行比较<br>
* 按照比较器链的顺序分别比较,如果比较出相等则转向下一个比较器,否则直接返回
*
* @param o1 第一个对象
* @param o2 第二个对象
* @return -1, 0, or 1
* @throws UnsupportedOperationException 如果比较器链为空,无法完成比较
*/
@Override
public
int
compare
(
final
E
o1
,
final
E
o2
)
throws
UnsupportedOperationException
{
if
(
lock
==
false
)
{
checkChainIntegrity
();
lock
=
true
;
}
final
Iterator
<
Comparator
<
E
>>
comparators
=
chain
.
iterator
();
Comparator
<?
super
E
>
comparator
;
int
retval
;
for
(
int
comparatorIndex
=
0
;
comparators
.
hasNext
();
++
comparatorIndex
)
{
comparator
=
comparators
.
next
();
retval
=
comparator
.
compare
(
o1
,
o2
);
if
(
retval
!=
0
)
{
// invert the order if it is a reverse sort
if
(
true
==
orderingBits
.
get
(
comparatorIndex
))
{
retval
=
(
retval
>
0
)
?
-
1
:
1
;
}
return
retval
;
}
}
// if comparators are exhausted, return 0
return
0
;
}
@Override
public
int
hashCode
()
{
int
hash
=
0
;
if
(
null
!=
chain
)
{
hash
^=
chain
.
hashCode
();
}
if
(
null
!=
orderingBits
)
{
hash
^=
orderingBits
.
hashCode
();
}
return
hash
;
}
@Override
public
boolean
equals
(
final
Object
object
)
{
if
(
this
==
object
)
{
return
true
;
}
if
(
null
==
object
)
{
return
false
;
}
if
(
object
.
getClass
().
equals
(
this
.
getClass
()))
{
final
ComparatorChain
<?>
otherChain
=
(
ComparatorChain
<?>)
object
;
//
return
Objects
.
equals
(
this
.
orderingBits
,
otherChain
.
orderingBits
)
&&
this
.
chain
.
equals
(
otherChain
.
chain
);
}
return
false
;
}
//------------------------------------------------------------------------------------------------------------------------------- Private method start
/**
* 被锁定时抛出异常
*
* @throws UnsupportedOperationException 被锁定抛出此异常
*/
private
void
checkLocked
()
{
if
(
lock
==
true
)
{
throw
new
UnsupportedOperationException
(
"Comparator ordering cannot be changed after the first comparison is performed"
);
}
}
/**
* 检查比较器链是否为空,为空抛出异常
*
* @throws UnsupportedOperationException 为空抛出此异常
*/
private
void
checkChainIntegrity
()
{
if
(
chain
.
size
()
==
0
)
{
throw
new
UnsupportedOperationException
(
"ComparatorChains must contain at least one Comparator"
);
}
}
//------------------------------------------------------------------------------------------------------------------------------- Private method start
}
hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorException.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
cn.hutool.core.exceptions.ExceptionUtil
;
import
cn.hutool.core.util.StrUtil
;
/**
* 比较异常
* @author xiaoleilu
*/
public
class
ComparatorException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
4475602435485521971L
;
public
ComparatorException
(
Throwable
e
)
{
super
(
ExceptionUtil
.
getMessage
(
e
),
e
);
}
public
ComparatorException
(
String
message
)
{
super
(
message
);
}
public
ComparatorException
(
String
messageTemplate
,
Object
...
params
)
{
super
(
StrUtil
.
format
(
messageTemplate
,
params
));
}
public
ComparatorException
(
String
message
,
Throwable
throwable
)
{
super
(
message
,
throwable
);
}
public
ComparatorException
(
Throwable
throwable
,
String
messageTemplate
,
Object
...
params
)
{
super
(
StrUtil
.
format
(
messageTemplate
,
params
),
throwable
);
}
}
hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
java.util.Comparator
;
import
java.util.Objects
;
import
java.util.function.Function
;
/**
* 比较工具类
*
* @author looly
*/
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接口)
*
* <p>
* 一般而言,如果c1 < c2,返回数小于0,c1==c2返回0,c1 > c2 大于0
*
* @param <T> 被比较对象类型
* @param c1 对象1
* @param c2 对象2
* @param comparator 比较器
* @return 比较结果
* @see java.util.Comparator#compare(Object, Object)
* @since 4.6.9
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
static
<
T
>
int
compare
(
T
c1
,
T
c2
,
Comparator
<
T
>
comparator
)
{
if
(
null
==
comparator
)
{
return
compare
((
Comparable
)
c1
,
(
Comparable
)
c2
);
}
return
comparator
.
compare
(
c1
,
c2
);
}
/**
* {@code null}安全的对象比较,{@code null}对象小于任何对象
*
* @param <T> 被比较对象类型
* @param c1 对象1,可以为{@code null}
* @param c2 对象2,可以为{@code null}
* @return 比较结果,如果c1 < c2,返回数小于0,c1==c2返回0,c1 > c2 大于0
* @see java.util.Comparator#compare(Object, Object)
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
int
compare
(
T
c1
,
T
c2
)
{
return
compare
(
c1
,
c2
,
false
);
}
/**
* {@code null}安全的对象比较
*
* @param <T> 被比较对象类型(必须实现Comparable接口)
* @param c1 对象1,可以为{@code null}
* @param c2 对象2,可以为{@code null}
* @param isNullGreater 当被比较对象为null时是否排在后面,true表示null大于任何对象,false反之
* @return 比较结果,如果c1 < c2,返回数小于0,c1==c2返回0,c1 > c2 大于0
* @see java.util.Comparator#compare(Object, Object)
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
int
compare
(
T
c1
,
T
c2
,
boolean
isNullGreater
)
{
if
(
c1
==
c2
)
{
return
0
;
}
else
if
(
c1
==
null
)
{
return
isNullGreater
?
1
:
-
1
;
}
else
if
(
c2
==
null
)
{
return
isNullGreater
?
-
1
:
1
;
}
return
c1
.
compareTo
(
c2
);
}
/**
* 自然比较两个对象的大小,比较规则如下:
*
* <pre>
* 1、如果实现Comparable调用compareTo比较
* 2、o1.equals(o2)返回0
* 3、比较hashCode值
* 4、比较toString值
* </pre>
*
* @param <T> 被比较对象类型
* @param o1 对象1
* @param o2 对象2
* @param isNullGreater null值是否做为最大值
* @return 比较结果,如果o1 < o2,返回数小于0,o1==o2返回0,o1 > o2 大于0
*/
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
public
static
<
T
>
int
compare
(
T
o1
,
T
o2
,
boolean
isNullGreater
)
{
if
(
o1
==
o2
)
{
return
0
;
}
else
if
(
null
==
o1
)
{
// null 排在后面
return
isNullGreater
?
1
:
-
1
;
}
else
if
(
null
==
o2
)
{
return
isNullGreater
?
-
1
:
1
;
}
if
(
o1
instanceof
Comparable
&&
o2
instanceof
Comparable
)
{
//如果bean可比较,直接比较bean
return
((
Comparable
)
o1
).
compareTo
(
o2
);
}
if
(
o1
.
equals
(
o2
))
{
return
0
;
}
int
result
=
Integer
.
compare
(
o1
.
hashCode
(),
o2
.
hashCode
());
if
(
0
==
result
)
{
result
=
compare
(
o1
.
toString
(),
o2
.
toString
());
}
return
result
;
}
/**
* 中文比较器
*
* @param keyExtractor 从对象中提取中文(参与比较的内容)
* @param <T> 对象类型
* @return 中文比较器
* @since 5.4.3
*/
public
static
<
T
>
Comparator
<
T
>
comparingPinyin
(
Function
<
T
,
String
>
keyExtractor
)
{
return
comparingPinyin
(
keyExtractor
,
false
);
}
/**
* 中文(拼音)比较器
*
* @param keyExtractor 从对象中提取中文(参与比较的内容)
* @param reverse 是否反序
* @param <T> 对象类型
* @return 中文比较器
* @since 5.4.3
*/
public
static
<
T
>
Comparator
<
T
>
comparingPinyin
(
Function
<
T
,
String
>
keyExtractor
,
boolean
reverse
)
{
Objects
.
requireNonNull
(
keyExtractor
);
PinyinComparator
pinyinComparator
=
new
PinyinComparator
();
if
(
reverse
)
{
return
(
o1
,
o2
)
->
pinyinComparator
.
compare
(
keyExtractor
.
apply
(
o2
),
keyExtractor
.
apply
(
o1
));
}
return
(
o1
,
o2
)
->
pinyinComparator
.
compare
(
keyExtractor
.
apply
(
o1
),
keyExtractor
.
apply
(
o2
));
}
/**
* 索引比较器<br>
* 通过keyExtractor函数,提取对象的某个属性或规则,根据提供的排序数组,完成比较<br>
*
* @param keyExtractor 从对象中提取中文(参与比较的内容)
* @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
* @param <T> 对象类型
* @param <U> 数组对象类型
* @return 索引比较器
* @since 5.8.0
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
,
U
>
Comparator
<
T
>
comparingIndexed
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
,
U
...
objs
)
{
return
comparingIndexed
(
keyExtractor
,
false
,
objs
);
}
/**
* 索引比较器<br>
* 通过keyExtractor函数,提取对象的某个属性或规则,根据提供的排序数组,完成比较<br>
*
* @param keyExtractor 从对象中提取排序键的函数(参与比较的内容)
* @param atEndIfMiss 如果不在列表中是否排在后边
* @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
* @param <T> 对象类型
* @param <U> 数组对象类型
* @return 索引比较器
* @since 5.8.0
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
,
U
>
Comparator
<
T
>
comparingIndexed
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
,
boolean
atEndIfMiss
,
U
...
objs
)
{
Objects
.
requireNonNull
(
keyExtractor
);
IndexedComparator
<
U
>
indexedComparator
=
new
IndexedComparator
<>(
atEndIfMiss
,
objs
);
return
(
o1
,
o2
)
->
indexedComparator
.
compare
(
keyExtractor
.
apply
(
o1
),
keyExtractor
.
apply
(
o2
));
}
}
hutool-core/src/main/java/cn/hutool/core/comparator/FieldComparator.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.comparator
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.util.ClassUtil
;
import
cn.hutool.core.util.ReflectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
java.lang.reflect.Field
;
/**
* Bean字段排序器<br>
* 参阅feilong-core中的PropertyComparator
*
* @param <T> 被比较的Bean
* @author Looly
*/
public
class
FieldComparator
<
T
>
extends
FuncComparator
<
T
>
{
private
static
final
long
serialVersionUID
=
9157326766723846313L
;
/**
* 构造
*
* @param beanClass Bean类
* @param fieldName 字段名
*/
public
FieldComparator
(
Class
<
T
>
beanClass
,
String
fieldName
)
{
this
(
getNonNullField
(
beanClass
,
fieldName
));
}
/**
* 构造
*
* @param field 字段
*/
public
FieldComparator
(
Field
field
)
{
this
(
true
,
field
);
}
/**
* 构造
*
* @param nullGreater 是否{@code null}在后
* @param field 字段
*/
public
FieldComparator
(
boolean
nullGreater
,
Field
field
)
{
super
(
nullGreater
,
(
bean
)
->
(
Comparable
<?>)
ReflectUtil
.
getFieldValue
(
bean
,
Assert
.
notNull
(
field
,
"Field must be not null!"
)));
}
/**
* 获取字段,附带检查字段不存在的问题。
*
* @param beanClass Bean类
* @param fieldName 字段名
* @return 非null字段
*/
private
static
Field
getNonNullField
(
Class
<?>
beanClass
,
String
fieldName
)
{
final
Field
field
=
ClassUtil
.
getDeclaredField
(
beanClass
,
fieldName
);
if
(
field
==
null
)
{
throw
new
IllegalArgumentException
(
StrUtil
.
format
(
"Field [{}] not found in Class [{}]"
,
fieldName
,
beanClass
.
getName
()));
}
return
field
;
}
}
Prev
1
…
9
10
11
12
13
14
15
16
17
…
19
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment