考虑排序值相同的情况下取前几名数据工具
数据:[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}