zoukankan      html  css  js  c++  java
  • java 划分double区间练手示例Demo

    1. 前期准备

    ① 编辑器:Eclipse

    ② 构建工具:Maven

    ③ 第三方java开发工具:FastJSON, Guava

    2. 全部示例代码展示

      1 package com.drew.test;
      2 
      3 import java.math.BigDecimal;
      4 import java.util.Arrays;
      5 import java.util.Collections;
      6 import java.util.List;
      7 import java.util.Map;
      8 
      9 import com.alibaba.fastjson.JSON;
     10 import com.google.common.collect.ImmutableMap;
     11 import com.google.common.collect.Lists;
     12 import com.google.common.collect.Maps;
     13 
     14 /**
     15  * @author zero 2019/04/08
     16  */
     17 public class Java8future {
     18 
     19     public static void main(String[] args) {
     20         // System.out.println(genRandomRatio(0.75, 0.8, 2));
     21         // System.out.println(genRandomDoubleList(0.75, 0.8, 2, 2));
     22         // System.out.println(genRandomRatio(1, 8, 2));
     23         // System.out.println(genRandomDoubleList(1, 8, 2, 10));
     24         // System.out.println(genRandomInteger(1, 10));
     25         // System.out.println(testGenRandomIntegerList());
     26         // System.out.println(distributeInteger(Arrays.asList(1,2,3,6), 4));
     27         // testGeneratorDouble();
     28         // shuffleList();
     29         // testListSizeIsEqual();
     30         testRandomDistributeMap(); // MAIN-Test
     31         // System.out.println(doubleSecToTime(0.0));
     32 
     33     }
     34 
     35     /**
     36      * (double)秒转时分秒毫秒(HH:mm:ss:SSS)
     37      * 
     38      * @param seconds 秒(双精度类型的数据)
     39      * @return string类型的时分秒毫秒(HH:mm:ss:SSS)
     40      * @author zero 2019/04/11
     41      */
     42     public static String doubleSecToTime(double seconds) {
     43         if (seconds == 0.0) {
     44             return "0.0";
     45         }
     46         // 注意:BigDecimal.ROUND_HALF_UP:四舍五入、BigDecimal.ROUND_CEILING:向上取整
     47         double d = new BigDecimal(Double.toString(seconds)).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
     48         int msec = (int)(d * 1000) % 1000;
     49         // System.out.println(msec);
     50         int sec = (int)(d * 1000) / 1000;
     51         // System.out.println(sec);
     52         int hour = sec / 3600;
     53         int minute = (sec - hour * 3600) / 60;
     54         int second = (sec - hour * 3600 - minute * 60);
     55 
     56         StringBuffer sb = new StringBuffer();
     57         if (hour > 0) {
     58             sb.append(hour + "h");
     59         }
     60         if (minute > 0) {
     61             sb.append(minute + "m");
     62         }
     63         if (second > 0) {
     64             sb.append(second + "s");
     65         }
     66         if (msec != 0) {
     67             sb.append(msec + "ms");
     68         }
     69         return sb.toString();
     70     }
     71 
     72     public static List<Integer> testGenRandomIntegerList() {
     73         List<Integer> list = Lists.newArrayList();
     74         for (int i = 0; i < 20; i++) {
     75             list.add(genRandomInteger(5, 10));
     76         }
     77         return list;
     78     }
     79 
     80     // ========================↓↓↓ 测试map根据key分区 ↓↓↓==========================
     81     public static void testRandomDistributeMap() {
     82         Map<Double, Integer> map = Maps.newLinkedHashMap();
     83         // 1. 为了测试,随机生成map数据
     84         int mapKeyCount = 20;
     85         // int range = 10; // 每个值的范围区间
     86         for (int i = 0; i < mapKeyCount; i++) {
     87             // double key = new BigDecimal(Math.random() * range).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
     88             // Integer value = new BigDecimal(Math.random() * range).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
     89             double key = genRandomRatio(1, 10, 2);// 每个double类型数据值范围区间:[1,10],精确度为2.
     90             Integer value = (int)genRandomRatio(1, 10, 0);// 每个double类型数据值范围区间:[1,10],精确度为0.(是int类型)
     91             map.put(key, value);
     92             System.out.print(key + " ");
     93         }
     94         System.out.println("
    随机生成的map:" + map);
     95         // 2. 对map进行排序:
     96         Map<Double, Integer> sortedMapByKey = sortByKey(map, false);
     97         System.out.println("按key↑排map:" + sortedMapByKey);
     98         Map<Double, Integer> sortedMapByValue = sortByValue(map, true);
     99         System.out.println("按val↓排map:" + sortedMapByValue);
    100         // 3. 调用划分区间的方法this.randomDistribute(map,ratio)方法
    101         double ratio = genRandomRatio(0.75, 0.8, 2);
    102         System.out.println("随机生成的比值为:" + ratio);
    103         Map<String, Integer> result = randomDistribute(sortedMapByValue, ratio);
    104         // 4. 输出result数据
    105         for (String timeNode : result.keySet()) {
    106             System.out.println(timeNode + "   	" + result.get(timeNode));
    107         }
    108         // 5. 组装前端所需的数据格式:树状图(同chart数据格式)
    109         Map<String, Object> needResultFormatterMap = Maps.newHashMap();
    110         needResultFormatterMap.put("attrDetails", ImmutableMap.of("axis", result.keySet(), "data", result.values(),
    111             "field", "avg_spent_time", "legend", "平均时长分布"));
    112         System.out.println(JSON.toJSONString(needResultFormatterMap));
    113     }
    114 
    115     /**
    116      * 将map数据按照key分隔区间
    117      * 
    118      * @param map key:时刻,value:访客数(time-visits)
    119      * @param ratio 比值(重点查看多少比例的数据)
    120      * @return Map<String, Integer>中,key:时间区间,value:访问数
    121      * @author zero 2019/04/10
    122      */
    123     public static Map<String, Integer> randomDistribute(Map<Double, Integer> map, double ratio) {
    124         if (map.isEmpty()) {
    125             return ImmutableMap.of("No data!", 0);
    126         }
    127         Map<String, Integer> result = Maps.newLinkedHashMap();
    128         double sum = map.values().stream().reduce((a, b) -> a + b).get();// map的value累加求和。
    129         double dirtributeNode = Math.round(sum * ratio);
    130         System.out.println("所有访客数:" + sum + ",划分节点:" + dirtributeNode);
    131         // 第一次划分区间:(8--2)
    132         Map<Double, Integer> tMap = Maps.newLinkedHashMap();
    133         long tmpSum = 0;
    134         for (Double key : map.keySet()) {
    135             tmpSum += map.get(key);
    136             if (tmpSum <= dirtributeNode) {
    137                 tMap.put(key, map.get(key));
    138             } else {
    139                 tMap.put(key, map.get(key));
    140                 break;
    141             }
    142         }
    143         System.out.println("第一次按照比值截取之后的map:" + tMap);
    144         Map<Double, Integer> afterRatioMap = sortByKey(tMap, false);
    145         System.out.println("按key↑排map:" + afterRatioMap);
    146         List<Double> keys = Lists.newArrayList(afterRatioMap.keySet());
    147         // 对keys集合分区间:
    148         List<List<Double>> indexList = distributeDouble(keys, genRandomInteger(30, 60), 2);
    149         // System.out.println("固定划分好的区间段:" + distributeDouble(keys, 60, 2));
    150 
    151         for (List<Double> list : indexList) {
    152             // start为一小段的闭区间,end:为一小段的开区间。如:list为[1,5]表示的值范围为[1,5)即 1<=x<5,但是indexList中如果list为最后一个,最为双闭区间
    153             // 注意:如果划分之后的区间,list无元素存在;则不显示此区间的个数为0.(根据需求更改:无元素在此区间,也得显示区间的元素为0.)
    154             Integer tmp = 0;
    155             double start = list.get(0), end = list.get(1);
    156             for (Double timeKey : afterRatioMap.keySet()) {
    157                 if (indexList.indexOf(list) == indexList.size() - 1) {
    158                     if (start <= timeKey && timeKey <= end) {
    159                         tmp = result.get("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + "]") == null ? 0
    160                             : result.get("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + "]");
    161                         result.put("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + "]",
    162                             tmp + afterRatioMap.get(timeKey));
    163                     }
    164                 } else {
    165                     if (start <= timeKey && timeKey < end) {
    166                         tmp = result.get("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + ")") == null ? 0
    167                             : result.get("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + ")");
    168                         result.put("[" + doubleSecToTime(start) + "," + doubleSecToTime(end) + ")",
    169                             tmp + afterRatioMap.get(timeKey));
    170                     }
    171                 }
    172             }
    173         }
    174         return result;
    175     }
    176 
    177     /**
    178      * 随机生成一个[low,high]双闭区间中随机的一个double类型数据
    179      * 
    180      * @param low 最小值(包含)
    181      * @param high 最大值(包含)
    182      * @param effective_number double类型的精度(如果effective_number=3,则保留三位有效数字)
    183      * @return [low,high]双闭区间中随机的一个double类型数据,例如:0.77
    184      * @author zero 2019/04/10
    185      */
    186     public static double genRandomRatio(double low, double high, int effective_number) {
    187         double d = new BigDecimal(Double.toString(Math.random() * (high - low) + low))
    188             .setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
    189         return d;
    190     }
    191 
    192     public static int genRandomInteger(int low, int high) {
    193         return new BigDecimal(Math.random() * (high - low + 1) + low).intValue();
    194     }
    195 
    196     /**
    197      * 随机生成一个[low,high]双闭区间中随机count个数的double类型数据的list集合
    198      * 
    199      * @param low 最小值(包含)
    200      * @param high 最大值(包含)
    201      * @param effective_number double类型的精度(如果effective_number=3,则保留三位有效数字)
    202      * @param count list大小(即生成多少个随机数字)
    203      * @return
    204      * @author zero 2019/04/10
    205      */
    206     public static List<Double> genRandomDoubleList(double low, double high, int effective_number, int count) {
    207         List<Double> randomDouble = Lists.newArrayList();
    208         for (int i = 0; i < count; i++) {
    209             double d = new BigDecimal(Double.toString(Math.random() * (high - low) + low))
    210                 .setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
    211             randomDouble.add(d);
    212         }
    213         return randomDouble;
    214     }
    215 
    216     /**
    217      * 将integer类型的集合按照区间个数划分固定区间范围的多个子集合(左开右闭) TODO 可以借鉴distributeDouble()方法的分区间原理
    218      * 
    219      * @param list 待划分的区间
    220      * @param count 区间个数
    221      * @return
    222      * @author zero 2019/04/10
    223      */
    224     public static List<List<Integer>> distributeInteger(List<Integer> list, int count) {
    225         Collections.sort(list);
    226         int min = list.get(0);
    227         int max = list.get(list.size() - 1);
    228         // TODO 特殊情况:当list为:1,2,3,4时,区间格式为4,则结果为[[1, 2], [2, 3], [3, 4], [4, 5]]。即最后一个区间[4,5]是没有数据的
    229         int range = (max - min) / count == 0 ? 1 : (max - min) / count;
    230         System.out.println("最大值:" + max + "	最小值:" + min + "	区间范围:" + range);
    231         List<List<Integer>> resultList = Lists.newArrayList();
    232         int tmpStart = min, b1, b2;
    233         for (int i = 0; i < count; i++) {
    234             b1 = tmpStart;
    235             b2 = range;
    236             resultList.add(Arrays.asList(b1, b1 + b2));
    237             tmpStart = b1 + b2;
    238         }
    239         if (tmpStart < max) {
    240             resultList.add(Arrays.asList(tmpStart, max));
    241         }
    242         return resultList;
    243     }
    244 
    245     /**
    246      * 分散有序的list集合(打乱有序集合)
    247      * 
    248      * @author zero 2019/04/10
    249      */
    250     public static void shuffleList() {
    251         List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
    252         Collections.shuffle(list);// 打乱初始的list集合。
    253         System.out.println(list.get(0));
    254     }
    255 
    256     // ========================↓↓↓ double集合分区 ↓↓↓==========================
    257     public static void testGeneratorDouble() {
    258         int effective_number = 3;// 生成double值的精确度
    259         int length = 15;// 生成list集合数量
    260         int range = 100;// 每个数字的范围
    261         int space = 5; // 划分十个区间
    262         // 随机生成
    263         List<Double> list = generatorDouble(effective_number, length, range);
    264         System.out.println(list);
    265         // 不定区间-碰撞算法
    266 
    267         // 固定区间-划分
    268         List<List<Double>> distributeList = distributeDouble(list, space, effective_number);
    269         System.out.println(distributeList);
    270     }
    271 
    272     /**
    273      * 生成双精度类型的list集合数据
    274      * 
    275      * @param effective_number 生成double值的精确度
    276      * @param length 生成list集合数量
    277      * @param range 每个值所在区间[0,100]
    278      * @return
    279      * @author zero 2019/04/09
    280      */
    281     public static List<Double> generatorDouble(int effective_number, int length, int range) {
    282         List<Double> randomList = Lists.newArrayList();
    283         for (int i = 0; i < length; i++) {
    284             // 如:取0-100随机数,则range=100
    285             BigDecimal temp = new BigDecimal(Math.random() * range);
    286             // 如:取effective_number=3位有效位
    287             double add_data = temp.setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
    288             randomList.add(add_data);
    289         }
    290         return randomList;
    291     }
    292 
    293     /**
    294      * 将list集合划分固定范围区间(每小段区间范围是固定的)
    295      * 
    296      * @param list double集合
    297      * @param space 需要划分的具体区间数字,例如:10为划分十个区间
    298      * @param effective_number 每个值的精确度
    299      * @author zero 2019/04/09
    300      */
    301     public static List<List<Double>> distributeDouble(List<Double> list, int space, int effective_number) {
    302         // 针对double划分区间
    303         Collections.sort(list);
    304         double min = list.get(0);
    305         double max = list.get(list.size() - 1);
    306         double range = (max - min) / space;
    307         BigDecimal temp = new BigDecimal(range);
    308         range = temp.setScale(effective_number, BigDecimal.ROUND_HALF_UP).doubleValue();
    309         // ↑↑划分区间的核心代码 ↑↑
    310 
    311         // 显示每个划分好的固定区间的范围
    312         List<List<Double>> distributeList = Lists.newArrayList();
    313         double tmpStart = min;
    314         BigDecimal b1, b2;
    315         for (int i = 0; i < space; i++) {
    316             b1 = new BigDecimal(Double.toString(tmpStart));
    317             b2 = new BigDecimal(Double.toString(range));
    318             // System.out.println("[" + b1.doubleValue() + "," + b1.add(b2).doubleValue() + ")");// 左闭右开
    319             distributeList.add(Arrays.asList(b1.doubleValue(), b1.add(b2).doubleValue()));
    320             tmpStart = b1.add(b2).doubleValue();
    321         }
    322         if (tmpStart < max) {
    323             distributeList.add(Arrays.asList(tmpStart, max));
    324         }
    325         System.out.println("最小值:" + min + "	最大值:" + max + "	区间值:" + range + "	区间个数为:" + distributeList.size());
    326         return distributeList;
    327     }
    328 
    329     // ========================↓↓↓ 对map进行排序 ↓↓↓==========================
    330     public static void testSortMap() {
    331         Map<String, Integer> map = ImmutableMap.of("0", 3, "1", 8, "0.29", 7, "1.67", 3);
    332         System.out.println("原始的map:" + map);
    333         System.out.println("根据map的key降序:" + sortByKey(map, true));
    334         System.out.println("根据map的key升序:" + sortByKey(map, false));
    335         System.out.println("根据map的value降序:" + sortByValue(map, true));
    336         System.out.println("根据map的value升序:" + sortByValue(map, false));
    337     }
    338 
    339     /**
    340      * 根据map的key排序(如果map中的key为Integer类型的字符串,请将map中的key设置为Integer)
    341      * 
    342      * @param map 待排序的map
    343      * @param isDesc 是否降序,true:降序,false:升序
    344      * @return 排序好的map
    345      * @author zero 2019/04/08
    346      */
    347     public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
    348         Map<K, V> result = Maps.newLinkedHashMap();
    349         if (isDesc) {
    350             map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
    351                 .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
    352         } else {
    353             map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
    354                 .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
    355         }
    356         return result;
    357     }
    358 
    359     /**
    360      * 根据map的value排序
    361      * 
    362      * @param map 待排序的map
    363      * @param isDesc 是否降序,true:降序,false:升序
    364      * @return 排序好的map
    365      * @author zero 2019/04/08
    366      */
    367     public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, boolean isDesc) {
    368         Map<K, V> result = Maps.newLinkedHashMap();
    369         if (isDesc) {
    370             map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue().reversed())
    371                 .forEach(e -> result.put(e.getKey(), e.getValue()));
    372         } else {
    373             map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue())
    374                 .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
    375         }
    376         return result;
    377     }
    378 
    379 }

    3. 示例结果展示

  • 相关阅读:
    Java实现 LeetCode 50 Pow(x,n)
    Java实现 LeetCode 50 Pow(x,n)
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 47 全排列 II(二)
    Java实现 LeetCode 47 全排列 II(二)
  • 原文地址:https://www.cnblogs.com/superdrew/p/10700654.html
Copyright © 2011-2022 走看看