package test;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by zzq on 2020/11/27.
*/
public class RangeProcessor {
private Map<String, List<Range>> mediaAgeRangeMap;
/**
* 该构造函数期望应用首次启动调用
* (非线程安全)
*
* @param rangeList
*/
public RangeProcessor(List<Range> rangeList) {
if (rangeList == null) {
throw new RuntimeException("rangeList不能为空");
}
mediaAgeRangeMap = new HashMap<>();
for (int i = 0; i < rangeList.size(); i++) {
Range range = rangeList.get(i);
range.initSegmentList();
List<Long> segmentList = range.getSegmentList();
if (segmentList == null || segmentList.size() == 0) {
throw new RuntimeException("Range对象segmentList属性不允许为空,请检查Range#getBinRangeStr返回值是否为二进制字符串");
}
String typeId = range.getTypeId();
List<Range> innerRangeList = mediaAgeRangeMap.get(typeId);
if (innerRangeList == null) {
innerRangeList = new ArrayList<>();
mediaAgeRangeMap.put(typeId, innerRangeList);
}
innerRangeList.add(range);
}
}
/**
* 根据媒体id以及输入的二进制字符串,获取范围标记列表,并升序排列
* (腾讯专用)
*
* @param typeId
* @param binAgeRangeStr
* @param tencent
* @return
* @throws Exception
*/
public List<String> getRangeTagList(String typeId, String binAgeRangeStr, boolean tencent) {
checkBinAgeRange(binAgeRangeStr);
if (tencent) {//处理腾讯逻辑
int startIndex = -1;
int endIndex = -1;
for (int i = 0; i < binAgeRangeStr.length(); i++) {
char currChar = binAgeRangeStr.charAt(i);
if (startIndex == -1 && currChar == 49) {//起始位置
endIndex = startIndex = i;
}
if (startIndex != -1 && currChar == 48) {//开始索引位置标记后,以0为标识寻找结束位置
endIndex = i - 1;
break;
}
}
List<String> retRangeTagList = new ArrayList<>();
retRangeTagList.add(startIndex + "");
retRangeTagList.add(endIndex + "");
return retRangeTagList;
}
return getRangeTagList(typeId, binAgeRangeStr);
}
/**
* 根据媒体id以及输入的二进制字符串,获取范围标记列表,并升序排列
*
* @param typeId
* @param binAgeRangeStr
* @return
*/
public List<String> getRangeTagList(String typeId, String binAgeRangeStr) {
checkBinAgeRange(binAgeRangeStr);
if (mediaAgeRangeMap == null) {
throw new RuntimeException("未调用AgeRangeProcessor构造函数");
}
List<Range> rangeList = mediaAgeRangeMap.get(typeId);
if (rangeList == null) {
throw new RuntimeException("找不到typeId标识的区间,或未调用RangeProcessor构造函数");
}
List<String> retAgeRangeNoList = new ArrayList<>();
for (int i = 0; i < rangeList.size(); i++) {
Range range = rangeList.get(i);
if (range.getBinRangeStr() == null || range.getBinRangeStr().length() != binAgeRangeStr.length()) {
throw new RuntimeException("传入的二进制字符串长度,与初始化的对比字符串长度不同;或初始化字符串为空,Range#getBinRangeStr方法不允许返回空");
}
if (segmentCheck(range, binAgeRangeStr)) {
retAgeRangeNoList.add(range.getRangeTag());
}
}
return retAgeRangeNoList;
}
private boolean segmentCheck(Range range, String binAgeRangeStr) {
List<Long> segmentList = range.getSegmentList();
List<Long> inputSegmentList = createSegment(binAgeRangeStr);
for (int i = 0; i < segmentList.size(); i++) {
Long segmentBin = segmentList.get(i);
Long inputSegmentBin = inputSegmentList.get(i);
if ((segmentBin & inputSegmentBin) != segmentBin) {
return false;
}
}
return true;
}
static List<Long> createSegment(String binAgeRangeStr) {
int length = binAgeRangeStr.length();
int segmentNum = length >> 5;
List<Long> segmentList = new ArrayList<>();
int start = 0;
for (int i = 0; i < segmentNum; i++) {
int end = start + 32;
addSegmentRadix2Long(binAgeRangeStr, segmentList, start, end);
start = end;
}
if (start < length) {
addSegmentRadix2Long(binAgeRangeStr, segmentList, start, length);
}
return segmentList;
}
private static void addSegmentRadix2Long(String binAgeRangeStr, List<Long> segmentList, int start, int end) {
String segmentStr = binAgeRangeStr.substring(start, end);
segmentList.add(Long.parseLong(segmentStr, 2));
}
/**
* 不是数字,或者字符串为空,则直接返回
*
* @param binAgeRange
* @throws RuntimeException
*/
static void checkBinAgeRange(String binAgeRange) {
if (StringUtils.isBlank(binAgeRange) ||
!StringUtils.isNumeric(binAgeRange)) {
throw new RuntimeException("输入的二进制字符串不能为空,且格式为数字");
}
}
}
package test;
import java.util.List;
/**
* Created by zzq on 2020/11/27.
*/
public abstract class Range {
String typeId;//分类Id
String rangeTag;//范围记号
private List<Long> segmentList;
public List<Long> getSegmentList() {
return segmentList;
}
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public String getRangeTag() {
return rangeTag;
}
public void setRangeTag(String rangeTag) {
this.rangeTag = rangeTag;
}
abstract String getBinRangeStr();//需要设置binRangeStr二进制字符串
void initSegmentList() {
String binRangeStr = getBinRangeStr();
RangeProcessor.checkBinAgeRange(binRangeStr);
segmentList = RangeProcessor.createSegment(binRangeStr);
}
}
package test;
import lombok.Data;
/**
* Created by zzq on 2020/11/27.
*/
@Data
public class MediaAgeRange extends Range {
int startAge;
int endAge;
@Override
String getBinRangeStr() {
char ageRange[] = new char[128];
for (int i = 0; i < 128; i++) {
if (i >= startAge && i <= endAge)
ageRange[i] = 49;
else
ageRange[i] = 48;
}
return String.valueOf(ageRange);
}
}
package test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by zzq on 2020/11/27.
*/
public class Test {
public static void main(String[] args) throws Exception {
List<Range> mediaAgeRangeList = new ArrayList<>();
///*
//18岁以下
MediaAgeRange mediaAgeRange = new MediaAgeRange();
// mediaAgeRange.setBinAgeRange("01111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
mediaAgeRange.setStartAge(1);
mediaAgeRange.setEndAge(17);
mediaAgeRange.setRangeTag("1");
mediaAgeRange.setTypeId("baidu");
mediaAgeRangeList.add(mediaAgeRange);
//18-24岁
MediaAgeRange mediaAgeRange1 = new MediaAgeRange();
// mediaAgeRange1.setBinAgeRange("00000000000000000011111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
mediaAgeRange1.setStartAge(18);
mediaAgeRange1.setEndAge(24);
mediaAgeRange1.setRangeTag("2");
mediaAgeRange1.setTypeId("baidu");
mediaAgeRangeList.add(mediaAgeRange1);
//25-34岁
MediaAgeRange mediaAgeRange2 = new MediaAgeRange();
// mediaAgeRange2.setBinAgeRange("00000000000000000000000001111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
mediaAgeRange2.setStartAge(25);
mediaAgeRange2.setEndAge(34);
mediaAgeRange2.setRangeTag("3");
mediaAgeRange2.setTypeId("baidu");
mediaAgeRangeList.add(mediaAgeRange2);
//35-44岁
MediaAgeRange mediaAgeRange3 = new MediaAgeRange();
// mediaAgeRange3.setBinAgeRange("00000000000000000000000000000000000111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000");
mediaAgeRange3.setStartAge(35);
mediaAgeRange3.setEndAge(44);
mediaAgeRange3.setRangeTag("4");
mediaAgeRange3.setTypeId("baidu");
mediaAgeRangeList.add(mediaAgeRange3);
//44岁以上
MediaAgeRange mediaAgeRange4 = new MediaAgeRange();
// mediaAgeRange4.setBinAgeRange("00000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
// mediaAgeRange4.setBinAgeRange("00000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111");
mediaAgeRange4.setStartAge(45);
mediaAgeRange4.setEndAge(127);
mediaAgeRange4.setRangeTag("5");
mediaAgeRange4.setTypeId("baidu");
mediaAgeRangeList.add(mediaAgeRange4);
//*/
RangeProcessor rangeProcessor = new RangeProcessor(mediaAgeRangeList);
String abc = "00000000000000000011111111111111111000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111";
String uu = "00000000000000111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000";
List<String> ret = rangeProcessor.getRangeTagList("baidu", abc);
List<String> re1t = rangeProcessor.getRangeTagList("baidu", uu, true);
System.out.println();
}
}