考虑排序值相同的情况下取前几名数据工具
- 数据:[1,2,3,3,3,4,5]
a. 取前 3 名返回:[1,2,3,3,3]
b. 取前 4 名返回:[1,2,3,3,3]
- 数据:[1,2,3,4,5]
a. 取前 3 名返回:[1,2,3]
b. 取前 4 名返回:[1,2,3,4]
- 数据:[5,4,3,2,1]
a. 取前 3 名返回:[1,2,3]
b. 取前 4 名返回:[1,2,3,4]
工具类主体
import cn.hutool.core.collection.CollUtil;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@Getter
public class RankContext<T, V> {
private Collection<T> originalCollect;
private Function<T, V> valueMapper;
private Comparator<? super T> comparator;
private List<T> sortedCollect;
private List<V> sortedValueList;
public static <T, V> RankContext<T, V> build(Collection<T> originalCollect,
Function<T, V> valueMapper,
Comparator<? super T> comparator) {
if (CollectionUtils.isEmpty(originalCollect)) {
return new RankContext<>();
}
List<T> sortedCollect = originalCollect.stream().sorted(comparator).collect(Collectors.toList());
List<V> sortedValueList = sortedCollect.stream().map(valueMapper).collect(Collectors.toList());
return new RankContext<>(originalCollect, valueMapper, comparator, sortedCollect, sortedValueList);
}
public List<T> top(int n) {
if (n < 1) {
return Collections.EMPTY_LIST;
}
if (this.sortedCollect.size() <= n) {
return new ArrayList<>(this.sortedCollect);
}
V value = this.sortedValueList.get(n);
int lastIndex = this.sortedValueList.lastIndexOf(value);
return CollUtil.sub(sortedCollect, 0, lastIndex + 1);
}
public int rank(V value) {
return this.sortedValueList.indexOf(value) + 1;
}
public int reverseRank(V value) {
return this.sortedValueList.size() - this.sortedValueList.lastIndexOf(value);
}
private RankContext() {
}
private RankContext(Collection<T> originalCollect,
Function<T, V> valueMapper,
Comparator<? super T> comparator,
List<T> sortedCollect,
List<V> sortedValueList) {
this.originalCollect = originalCollect;
this.valueMapper = valueMapper;
this.comparator = comparator;
this.sortedCollect = sortedCollect;
this.sortedValueList = sortedValueList;
}
}
测试类
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Comparator;
import java.util.List;
public class RankContextTest {
public static void main(String[] args) {
List<Student> collect = Lists.newArrayList(
new Student(1, 7),
new Student(2, 6),
new Student(3, 5),
new Student(3, 4),
new Student(3, 3),
new Student(3, 2),
new Student(4, 1)
);
System.out.println("按成绩排序取倒数 3 名");
List<Student> result = RankContext.build(collect, Student::getScore, Comparator.comparing(Student::getScore)).top(3);
for (Student student : result) {
System.out.println(student);
}
System.out.println("按成绩排序取前 3 名");
result = RankContext.build(collect, Student::getScore, Comparator.comparing(Student::getScore).reversed()).top(3);
for (Student student : result) {
System.out.println(student);
}
RankContext<Student, Integer> rankContext = RankContext.build(
collect,
Student::getRank,
Comparator.comparing(Student::getRank, Comparator.reverseOrder())
);
System.out.println("按排名排序取倒数 2 名");
result = rankContext.top(2);
for (Student student : result) {
System.out.println(student);
}
System.out.println("按排名排序取倒数 3 名");
result = rankContext.top(3);
for (Student student : result) {
System.out.println(student);
}
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Student {
private Integer score;
private Integer rank;
}
}
测试结果
按成绩排序取倒数 3 名
Student{score=1, rank=7}
Student{score=2, rank=6}
Student{score=3, rank=5}
Student{score=3, rank=4}
Student{score=3, rank=3}
Student{score=3, rank=2}
按成绩排序取前 3 名
Student{score=4, rank=1}
Student{score=3, rank=5}
Student{score=3, rank=4}
Student{score=3, rank=3}
Student{score=3, rank=2}
Student{score=2, rank=6}
按排名排序取倒数 2 名
Student{score=1, rank=7}
Student{score=2, rank=6}
按排名排序取倒数 3 名
Student{score=1, rank=7}
Student{score=2, rank=6}
Student{score=3, rank=5}