年齡使用128位二進位制字串進行儲存,這樣進行分段列舉時就可以保證,能夠快速靈活的標識每一段
阿新 • • 發佈:2020-12-02
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 (inti = 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 >> 6; List<Long> segmentList = new ArrayList<>(); int start = 0; for (int i = 0; i < segmentNum; i++) { int end = start + 64; addSegmentRadix2Long(binAgeRangeStr, segmentList, start + 1, 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(); } }