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("\n隨機生成的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 + "   \t" + 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 + "\t最小值:" + min + "\t區間范圍:" + 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 + "\t最大值:" + max + "\t區間值:" + range + "\t區間個數為:" + 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. 示例結果展示

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM