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("\n隨機生成的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 + "\n");
        // 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 + "   \t" + 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("\n升序后的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 + "\t最小值:" + min + "\t區間范圍:" + 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. 示例結果顯示:

 


免責聲明!

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



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