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(); } }