package com.walker.etaa.util;
|
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Random;
|
|
public class AlgorithmUtils {
|
|
private static final Logger logger = LoggerFactory.getLogger(AlgorithmUtils.class);
|
private static final Random random = new Random();
|
|
/**
|
* 返回给定数据的 HashCode 值集合。
|
* @param prefix 字符串前缀,如:math
|
* @param indexList 数据记录索引集合,如:[1,3,5,7,...]
|
* @return
|
* @date 2023-03-08
|
*/
|
public static final List<Integer> getHashCode(String prefix, int[] indexList){
|
if(indexList == null || indexList.length == 0){
|
return null;
|
}
|
List<Integer> resultList = new ArrayList<>(indexList.length + 8);
|
String s = null;
|
for(int i=0; i<indexList.length; i++){
|
s = prefix + indexList[i];
|
resultList.add(s.hashCode());
|
}
|
return resultList;
|
}
|
|
/**
|
* 返回给定范围可用的(随机)数据索引编号集合,如:
|
* <pre>
|
* [1,8,5,12,33,...]
|
* </pre>
|
* @param existTotal
|
* @param requiredTotal
|
* @return
|
*/
|
public static final int[] getRandomIndexArray(int existTotal, int requiredTotal){
|
int span = existTotal / requiredTotal;
|
int offset = 1;
|
if(span > 1){
|
offset = Math.abs(random.nextInt(span));
|
} else {
|
offset = Math.abs(random.nextInt(requiredTotal-1));
|
}
|
if(offset >= existTotal || offset <= 0){
|
offset = 1;
|
}
|
int count = 0;
|
List<Integer> data = new ArrayList<>();
|
while (count < requiredTotal){
|
if(offset >= existTotal || offset <= 0){
|
offset = Math.abs(random.nextInt(requiredTotal-1));
|
// logger.debug("------> offset = {}", offset);
|
}
|
if(!data.contains(offset)){
|
// logger.debug(".......... offset = {}", offset);
|
data.add(offset);
|
// offset = random.nextInt(requiredTotal-1) + span;
|
offset = Math.abs(random.nextInt(existTotal-1)) + span;
|
count ++;
|
logger.debug("count = {}, offset = {}", count, offset);
|
} else {
|
// 已有重复了,
|
// offset = count + 1;
|
offset = Math.abs(random.nextInt(existTotal-1));
|
logger.debug("重复了,offset = {}", offset);
|
}
|
}
|
if(data.size() > 0){
|
int[] resultList = new int[data.size()];
|
for(int i=0; i<data.size(); i++){
|
resultList[i] = data.get(i);
|
}
|
return resultList;
|
}
|
return null;
|
}
|
|
/**
|
* 返回给定范围可用的(平均分布)数据索引编号集合,如:
|
* <pre>
|
* [1,3,5,7,9,...]
|
* </pre>
|
* @param existTotal
|
* @param requiredTotal
|
* @return
|
*/
|
public static final int[] getAverageIndexArray(int existTotal, int requiredTotal){
|
int[] result = new int[requiredTotal];
|
int span = existTotal / requiredTotal;
|
int offset = Math.abs(random.nextInt(10));
|
logger.debug("offset = " + offset);
|
if(span == 1){
|
for(int i=0; i<requiredTotal; i++){
|
// System.out.println("get " + (i+1));
|
result[i] = i+1;
|
}
|
} else if(span > 1){
|
int current = offset;
|
if(current == 0){
|
current = 1;
|
}
|
|
int last = AlgorithmUtils.getAverageLastIndex(current, span, requiredTotal);
|
while(last > existTotal){
|
logger.debug("最后元素超过了'existTotal',last = " + last);
|
if(span > 1){
|
span --;
|
} else if(offset > 1){
|
offset --;
|
} else {
|
logger.warn("已经无法降低抽取间隔了,退出循环");
|
break;
|
}
|
last = AlgorithmUtils.getAverageLastIndex(current, span, requiredTotal);
|
}
|
|
for(int i=0; i<requiredTotal; i++){
|
if(i > 0){
|
current += span;
|
}
|
// System.out.println("get " + (current));
|
result[i] = current;
|
}
|
}
|
return result;
|
}
|
|
/**
|
* 返回平均分布方式抽取时,计算最后元素的索引值(计数值,是否超过题库最大值)
|
* @param first 第一个元素索引,从
|
* @param span
|
* @param requiredTotal
|
* @return
|
*/
|
public static final int getAverageLastIndex(int first, int span, int requiredTotal){
|
int current = first;
|
for(int i=0; i<requiredTotal; i++){
|
if(i > 0){
|
current += span;
|
}
|
// System.out.println("get " + (current));
|
}
|
return current;
|
}
|
}
|