获取随机key

import java.util.Set;

import io.netty.util.internal.ConcurrentSet;

/**
 * 获取key
 * 
 * @project common-utils
 * @fileName GetKey.java
 * @Description
 * @author light-zhang
 * @date 2018-10-12 17:10:33
 * @version 1.0.0
 */
public final class GetKey {

    private static final String baseDigits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
    private static final int BASE = baseDigits.length();
    private static final char[] digitsChar = baseDigits.toCharArray();
    private static final int FAST_SIZE = 'z';
    private static final int[] digitsIndex = new int[FAST_SIZE + 1];

    static {
        for (int i = 0; i < FAST_SIZE; i++) {
            digitsIndex[i] = -1;
        }
        for (int i = 0; i < BASE; i++) {
            digitsIndex[digitsChar[i]] = i;
        }
    }

    /**
     * 参数解码
     * 
     * @param paramter
     * @return
     */
    public static long decode(String paramter) {
        long result = 0L;
        synchronized (paramter) {
            long multiplier = 1;
            for (int pos = paramter.length() - 1; pos >= 0; pos--) {
                result += getIndex(paramter, pos) * multiplier;
                multiplier *= BASE;
            }
        }
        return result;
    }

    /**
     * 传入系统纳秒,防止重复
     * 
     * @param number
     * @return
     */
    public static String encode(Long number) {
        final StringBuilder builder = new StringBuilder();
        synchronized (number) {
            if (number < 0)
                new IllegalArgumentException("Number(Base64) must be positive: ".concat(number.toString()));
            if (number == 0)
                return "0";

            while (number != 0) {
                builder.append(digitsChar[(int) (number % BASE)]);
                number /= BASE;
            }
        }
        return builder.toString();
    }

    private static int getIndex(String paramter, int pmindex) {
        char c = paramter.charAt(pmindex);
        if (c > FAST_SIZE) {
            new IllegalArgumentException("Unknow character for Base64: ".concat(paramter));
        }
        int index = digitsIndex[c];
        if (index == -1) {
            new IllegalArgumentException("Unknow character for Base64: ".concat(paramter));
        }
        return index;
    }

    public static void main(String[] args) {
        Set<String> data = new ConcurrentSet<String>();
        for (int i = 0; i < 20000000; i++) {
            // System.out.println(encode(System.nanoTime()));
            data.add(encode(System.nanoTime()));
            // System.out.println(decode(UUID.randomUUID().toString()));
        }
        System.out.println(data.size());
        // System.out.println(decode("6c7P6dzh"));
    }
}

 

转载于:https://www.cnblogs.com/light-zhang/p/9779337.html

<think>首先,用户的问题是:“我想从Map中随机获取一个key的值 请问Java 如何从 Map 中随机获取一个 key 的值”。这是一个Java编程问题。 关键点: - 用户想从一个Map中随机获取一个key的值。 - 这意味着我需要提供一个Java代码示例来实现这个功能。 系统级指令: 1. 所有行内数学表达式必须使用$...$格式。但在这个问题中,没有数学表达式,所以可能不需要。如果有变量或代码相关的内容,我应该使用代码块。 2. 独立公式使用$$...$$格式。同样,这里没有公式。 3. LaTeX语法正确:确保如果使用数学表达式,LaTeX是正确的。 4. 使用中文回答:整个回答必须是中文。 5. 生成相关问题:在回答末尾,生成相关问题。 6. 回答中引用的段落末尾添加引用标识:如[^1]。但在这个问题中,没有引用来源,所以可能不需要添加,除非我引用某个知识。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 参考站内引用:系统提到“参考站内引用:。上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,这是第一条消息,没有“上一次的问题”。所以,我应该忽略这个部分。 现在,构建回答: 1. **理解需求**:用户想从一个Map中随机获取一个key的值。在Java中,Map接口没有直接的方法来随机获取键,所以我们需要手动实现。 2. **步骤**: - 获取Map的所有键。 - 从键集合中随机选择一个键。 - 使用该键获取值。 3. **代码示例**:提供Java代码来演示如何做到这一点。 4. **注意事项**:讨论可能的性能问题,例如如果Map很大,获取所有键可能效率不高。 5. **生成相关问题**:在末尾添加相关问题。 回答结构: - 开头解释问题。 - 逐步解释方法。 - 提供代码示例。 - 讨论优缺点。 - 生成相关问题。 代码示例: - 使用Map.keySet()获取键集合。 - 转换为List以便随机访问。 - 使用Random类生成随机索引。 - 然后获取值。 例如: ```java import java.util.*; public class RandomMapValue { public static <K, V> V getRandomValue(Map<K, V> map) { if (map == null || map.isEmpty()) { return null; // 或者抛出异常 } List<K> keys = new ArrayList<>(map.keySet()); Random random = new Random(); K randomKey = keys.get(random.nextInt(keys.size())); return map.get(randomKey); } } ``` 在回答中,使用中文解释。 生成相关问题: 例如: 1. 如何从Map中随机获取多个键的值? 2. 如果Map很大,如何高效地随机获取键? 3. Java中Map的其他常见操作有哪些? 确保回答真实可靠:基于标准Java知识。 最终回答格式: - 使用Markdown,代码块用```java```。 - 末尾添加“相关问题”。</think>### Java 如何从 Map 中随机获取一个 key 的值 在 Java 中,`Map` 接口本身没有直接提供随机获取键值的方法,但可以通过以下步骤实现: 1. **获取所有键的集合**:使用 `keySet()` 方法获取 Map 的所有键。 2. **转换为列表**:将键集合转换为列表(如 `ArrayList`),以便通过索引随机访问。 3. **生成随机索引**:使用 `Random` 类生成一个随机索引。 4. **获取键和值**:通过随机索引获取键,再用该键从 Map 中获取值。 以下是完整的代码示例: ```java import java.util.*; public class RandomMapValue { public static void main(String[] args) { // 示例:创建一个 Map Map<String, Integer> map = new HashMap<>(); map.put("A", 1); map.put("B", 2); map.put("C", 3); // 随机获取一个键的值 String randomKey = getRandomKey(map); Integer randomValue = map.get(randomKey); System.out.println("随机键: " + randomKey + ", 值: " + randomValue); } // 方法:从 Map 中随机获取一个键 public static <K> K getRandomKey(Map<K, ?> map) { if (map == null || map.isEmpty()) { throw new IllegalArgumentException("Map 不能为空或为空"); } List<K> keys = new ArrayList<>(map.keySet()); // 转换为列表 Random random = new Random(); int randomIndex = random.nextInt(keys.size()); // 生成随机索引 return keys.get(randomIndex); // 返回随机键 } } ``` #### 代码说明: - **输入处理**:如果 Map 为空或为 `null`,方法会抛出 `IllegalArgumentException` 以避免错误。 - **随机性保证**:使用 `Random.nextInt(int bound)` 确保索引均匀分布,保证每个键被选中的概率相等(假设键数量为 $n$,每个键的概率为 $\frac{1}{n}$)。 - **泛型支持**:方法使用泛型 `<K>`,适用于任何类型的 Map 键(如 `String`, `Integer` 等)。 - **性能考虑**: - **时间复杂度**:$O(1)$ 生成随机索引,但 `keySet()` 和列表转换需 $O(n)$ 时间($n$ 为键数量)。适合中小型 Map。 - **空间复杂度**:$O(n)$,因为需要存储键的列表。对于大型 Map(如百万级键),考虑优化方案(见下文)。 #### 优化建议(针对大型 Map): - **避免全量转换**:使用迭代器随机跳过元素,减少内存占用: ```java public static <K> K getRandomKeyOptimized(Map<K, ?> map) { if (map.isEmpty()) throw new IllegalArgumentException(); Random random = new Random(); int targetIndex = random.nextInt(map.size()); Iterator<K> iterator = map.keySet().iterator(); for (int i = 0; i < targetIndex; i++) { iterator.next(); // 跳过前 targetIndex 个元素 } return iterator.next(); // 返回随机键 } ``` - **线程安全**:如果 Map 可能被多线程修改,使用 `ConcurrentHashMap` 并加锁。 #### 注意事项: - 随机性依赖 `Random` 类,对于高安全性场景,改用 `SecureRandom`。 - 如果 Map 频繁修改,每次调用时重新生成键列表以保证一致性[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值