年龄使用128位二进制字符串进行存储,这样进行分段枚举时就可以保证,能够快速灵活的标识每一段

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

}
原文地址:https://www.cnblogs.com/zzq-include/p/14052249.html