zoukankan      html  css  js  c++  java
  • java实现划分Integer类型数据集合区间

    1. 描述:将integer类型的集合数据,按照比例进行固定区间划分。

    2. 示例全部代码:

    package com.drew.test;
    
    import java.math.BigDecimal;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.alibaba.fastjson.JSON;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    
    /**
     * @author zero 2019/04/10
     */
    public class DistributeIntegerList {
    
        public static void main(String[] args) {
            testRandomDistributeMap();
            // System.out.println("===================================");
            // System.out.println(genRandomInt(5, 10));
            // System.out.println(genRandomIntList(5, 10, 10));
            // System.out.println(genRandomDouble(5, 10, 2));
            // System.out.println(genRandomDoubleList(5, 10, 2, 20));
            // System.out.println("===================================");
        }
    
        /**
         * 本测试方法的整体思路: <br>
         * 要求:随机给定的map集合,按照value值的大小排序,截取一定比例的数据之后对截取的数据按照key正序之后----进行固定区间分组。
         * 
         * @author zero 2019/04/10
         */
        public static void testRandomDistributeMap() {
            Map<Integer, Integer> map = Maps.newLinkedHashMap();
            // 1. 为了测试,随机生成map数据
            int mapKeyCount = 50;// 生成随机数个数
            int range = 100;// 每个值的范围[1,100]
            for (int i = 0; i < mapKeyCount; i++) {
                int value = new BigDecimal(Math.random() * range).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
                int key = new BigDecimal(Math.random() * range).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
                map.put(key, value);
                System.out.print(key + " ");
            }
            System.out.println("
    随机生成的map:" + map);
            // 2. 对map进行排序:
            Map<Integer, Integer> sortedMapByKey = sortByKey(map, false);
            System.out.println("按key↑排map:" + sortedMapByKey);
            Map<Integer, Integer> sortedMapByValue = sortByValue(map, true);
            System.out.println("按val↓排map:" + sortedMapByValue + "
    ");
            // 3. 调用划分区间的方法this.randomDistribute(map,ratio)方法
            double ratio = genRandomDouble(0.75, 0.8, 2);
            System.out.println("随机生成的比值为:" + ratio);
            Map<String, Integer> result = randomDistribute(sortedMapByValue, ratio);
            // 4. 输出result数据
            for (String timeNode : result.keySet()) {
                System.out.println(timeNode + "   	" + result.get(timeNode));
            }
            // 5. 组装前端所需的数据格式:树状图(同chart数据格式)
            Map<String, Object> needResultFormatterMap = Maps.newLinkedHashMap();
            Map<String, Object> nodeNeedMap = Maps.newLinkedHashMap();
            nodeNeedMap.put("axis", result.keySet());
            nodeNeedMap.put("data", result.values());
            nodeNeedMap.put("field", "avg_spent_time");
            nodeNeedMap.put("legend", "平均时刻分布");
            needResultFormatterMap.put("attrDetails", nodeNeedMap);
            System.out.println("json格式:" + JSON.toJSONString(needResultFormatterMap));
        }
    
        /**
         * 将map数据按照key分隔区间
         * 
         * @param map key:时刻,value:访客数(time-visits)
         * @param ratio 比值(重点查看多少比例的数据)
         * @return Map<String, Integer>中,key:时间区间,value:访问数
         * @author zero 2019/04/10
         */
        public static Map<String, Integer> randomDistribute(Map<Integer, Integer> map, double ratio) {
            Map<String, Integer> result = Maps.newLinkedHashMap();
            long sum = map.values().stream().reduce((a, b) -> a + b).get();// map的value累加求和。
            long dirtributeNode = Math.round(sum * ratio);
            System.out.println("所有访客数:" + sum + ",划分节点:" + dirtributeNode);
            // 第一次划分区间:(8--2)
            Map<Integer, Integer> tMap = Maps.newLinkedHashMap();
            long tmpSum = 0;
            for (Integer key : map.keySet()) {
                tmpSum += map.get(key);
                if (tmpSum <= dirtributeNode) {
                    tMap.put(key, map.get(key));
                } else {
                    tMap.put(key, map.get(key));
                    break;
                }
            }
            System.out.println("第一次按照比值截取之后的map:" + tMap);
            Map<Integer, Integer> afterRatioMap = sortByKey(tMap, false);
            System.out.println("按key↑排map:" + afterRatioMap);
            List<Integer> keys = Lists.newArrayList(afterRatioMap.keySet());
            // 对keys集合分区间:TODO 区间是固定设置好的,可以随机生成区间数。可以调用此类中的genRandomInt()方法
            System.out.println("固定划分好的区间段:" + distributeInteger(keys, 5));
            List<List<Integer>> indexList = distributeInteger(keys, 5);
            for (List<Integer> list : indexList) {
                // start为一小段的闭区间,end:为一小段的开区间。如:list为[1,5]表示的值范围为[1,5)即 1<=x<5,但是indexList中如果list为最后一个,最为双闭区间
                // 注意:如果划分之后的区间,list无元素存在;则不显示此区间的个数为0.(根据需求更改:无元素在此区间,也得显示区间的元素为0.)
                Integer tmp = 0, start = list.get(0), end = list.get(1);
                for (Integer timeKey : afterRatioMap.keySet()) {
                    if (indexList.indexOf(list) == indexList.size() - 1) {
                        if (start <= timeKey && timeKey <= end) {
                            tmp = result.get("[" + start + "," + end + "]") == null ? 0
                                : result.get("[" + start + "," + end + "]");
                            result.put("[" + start + "," + end + "]", tmp + afterRatioMap.get(timeKey));
                        }
                    } else {
                        if (start <= timeKey && timeKey < end) {
                            tmp = result.get("[" + start + "," + end + ")") == null ? 0
                                : result.get("[" + start + "," + end + ")");
                            result.put("[" + start + "," + end + ")", tmp + afterRatioMap.get(timeKey));
                        }
                    }
                }
            }
            return result;
        }
    
        /**
         * 随机生成一个[low,high]双闭区间中随机的一个double类型数据
         * 
         * @param low 最小值(包含)
         * @param high 最大值(包含)
         * @param effective_number double类型的精度(如果effective_number=3,则保留三位有效数字)
         * @return [low,high]双闭区间中随机的一个double类型数据,例如:0.77
         * @author zero 2019/04/10
         */
        public static double genRandomDouble(double low, double high, int effective_number) {
            double d = new BigDecimal(Double.toString(Math.random() * (high - low) + low))
                .setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
            return d;
        }
    
        /**
         * 生成从low到high的随机整数[low,high]
         * 
         * @param low 最小值(包含)
         * @param high 最大值(包含)
         * @return
         * @author zero 2019/04/10
         */
        public static int genRandomInt(int low, int high) {
            int num = new BigDecimal((int)(Math.random() * (high - low + 1) + low)).intValue();
            return num;
        }
    
        /**
         * 随机生成一个[low,high]双闭区间中随机count个数的int类型数据的list集合
         * 
         * @param low 最小值(包含)
         * @param high 最大值(包含)
         * @param count list大小(即生成多少个)
         * @return
         * @author zero 2019/04/10
         */
        public static List<Integer> genRandomIntList(int low, int high, int count) {
            List<Integer> randomIntList = Lists.newArrayList();
            for (int i = 0; i < count; i++) {
                randomIntList.add(new BigDecimal((int)(Math.random() * (high - low + 1) + low)).intValue());
            }
            return randomIntList;
        }
    
        /**
         * 随机生成一个[low,high]双闭区间中随机count个数的double类型数据的list集合
         * 
         * @param low 最小值(包含)
         * @param high 最大值(包含)
         * @param effective_number double类型的精度(如果effective_number=3,则保留三位有效数字)
         * @param count list大小(即生成多少个)
         * @return
         * @author zero 2019/04/10
         */
        public static List<Double> genRandomDoubleList(double low, double high, int effective_number, int count) {
            List<Double> randomDouble = Lists.newArrayList();
            for (int i = 0; i < count; i++) {
                double d = new BigDecimal(Double.toString(Math.random() * (high - low) + low))
                    .setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
                randomDouble.add(d);
            }
            System.out.println("原始的doubleList:" + randomDouble);
            Collections.sort(randomDouble);
            System.out.println("
    升序后的doubleList:" + randomDouble);
            return randomDouble;
        }
    
        /**
         * 将integer类型的集合按照区间个数划分固定区间范围的多个子集合(左开右闭)
         * 
         * @param list 待划分的区间
         * @param count 区间个数
         * @return
         * @author zero 2019/04/10
         */
        public static List<List<Integer>> distributeInteger(List<Integer> list, int count) {
            Collections.sort(list);
            int min = list.get(0);
            int max = list.get(list.size() - 1);
            // TODO 特殊情况:当list为:1,2,3,4时,区间格式为4,则结果为[[1, 2], [2, 3], [3, 4], [4, 5]]。即最后一个区间[4,5]是没有数据的
            int range = (max - min) / count == 0 ? 1 : (max - min) / count;
    
            System.out.println("最大值:" + max + "	最小值:" + min + "	区间范围:" + range);
            List<List<Integer>> resultList = Lists.newArrayList();
            int tmpStart = min, b1, b2;
            for (int i = 0; i < count; i++) {
                b1 = tmpStart;
                b2 = range;
                resultList.add(Arrays.asList(b1, b1 + b2));
                tmpStart = b1 + b2;
            }
            if (tmpStart < max) {
                resultList.add(Arrays.asList(tmpStart, max));
            }
            return resultList;
        }
    
        /**
         * 根据map的key排序(如果map中的key为Integer类型的字符串,请将map中的key设置为Integer)
         * 
         * @param map 待排序的map
         * @param isDesc 是否降序,true:降序,false:升序
         * @return 排序好的map
         * @author zero 2019/04/08
         */
        public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
            Map<K, V> result = Maps.newLinkedHashMap();
            if (isDesc) {
                map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
            } else {
                map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
            }
            return result;
        }
    
        /**
         * 根据map的value排序
         * 
         * @param map 待排序的map
         * @param isDesc 是否降序,true:降序,false:升序
         * @return 排序好的map
         * @author zero 2019/04/08
         */
        public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, boolean isDesc) {
            Map<K, V> result = Maps.newLinkedHashMap();
            if (isDesc) {
                map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue().reversed())
                    .forEach(e -> result.put(e.getKey(), e.getValue()));
            } else {
                map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
            }
            return result;
        }
    
    }

    3. 示例结果显示:

  • 相关阅读:
    Java对象转型
    .Net之路(十二)Cookie对象
    java学习笔记-包
    MongoDB的安装和简单使用
    考试系统维护中对项目管理的一点体会
    .Net之路(十一)StringBuilder和string
    考试系统调试优化总结
    我的2013——走过就有收获
    针对:Arraylist集合无法修改,下一次枚举无法操作的解决方案
    函数第二部分:为什么说动态参数是没有计划好的参数-Python基础前传(11)
  • 原文地址:https://www.cnblogs.com/superdrew/p/10700587.html
Copyright © 2011-2022 走看看