1. 程式人生 > >java 劃分double區間練手示例Demo

java 劃分double區間練手示例Demo

src seq ash 需求 main val 設置 values linked

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. 示例結果展示

技術分享圖片

java 劃分double區間練手示例Demo