Java多类型键值对集合选型及并发任务重试存储方案问询
Hey there! Let's tackle your two Java collection requirements with practical, thread-safe solutions tailored to your use cases:
If you need a key-value store that can hold values of different data types, you've got a few solid options depending on how strict you want to be with type safety:
Raw
HashMap<Object, Object>(quick but less safe)
This lets you store any key-value pair, but you'll need to handle type checking manually when retrieving values to avoidClassCastException. Example:HashMap<Object, Object> multiTypeMap = new HashMap<>(); multiTypeMap.put("username", "john_doe"); multiTypeMap.put("age", 30); multiTypeMap.put("isActive", true); // Retrieving with type check if (multiTypeMap.get("age") instanceof Integer) { int age = (Integer) multiTypeMap.get("age"); }Custom Wrapper Class (type-safe approach)
If you know the specific types you'll be storing, create a wrapper class to encapsulate them. This eliminates casting headaches and makes your code more maintainable:class ValueWrapper { private String stringVal; private Integer intVal; private Boolean boolVal; // Constructors, getters, and setters for each type public ValueWrapper(String stringVal) { this.stringVal = stringVal; } public ValueWrapper(Integer intVal) { this.intVal = intVal; } public ValueWrapper(Boolean boolVal) { this.boolVal = boolVal; } // Add type-checking methods like isString(), isInteger() } HashMap<String, ValueWrapper> typeSafeMap = new HashMap<>(); typeSafeMap.put("username", new ValueWrapper("john_doe")); typeSafeMap.put("age", new ValueWrapper(30));
For your task execution framework, you need a thread-safe collection that tracks task IDs, task references, and retry counts. Here's a step-by-step solution:
Step 1: Create a Task Metadata Class
First, define a class to hold all the task-related data:
class TaskMetadata<T> { private final String taskId; private final Callable<T> task; private int retryCount; private static final int MAX_RETRIES = 3; public TaskMetadata(String taskId, Callable<T> task) { this.taskId = taskId; this.task = task; this.retryCount = 0; } // Getters and increment retry method public boolean canRetry() { return retryCount < MAX_RETRIES; } public void incrementRetryCount() { retryCount++; } // Getters for taskId, task, retryCount }
Step 2: Use a Thread-Safe Map for Storage
Since multiple threads will be interacting with this collection (task submitters and the polling thread), use ConcurrentHashMap—it's designed for concurrent access and provides O(1) lookups by task ID:
import java.util.concurrent.ConcurrentHashMap; ConcurrentHashMap<String, TaskMetadata<?>> taskMap = new ConcurrentHashMap<>(); // When submitting a task String taskId = "task-123"; Callable<String> task = () -> { /* Your task logic */ }; taskMap.put(taskId, new TaskMetadata<>(taskId, task)); // In your polling thread while (true) { // Poll CompletionService for results Future<?> future = completionService.poll(); if (future != null) { try { future.get(); // Task succeeded: remove from map taskMap.remove(taskId); } catch (Exception e) { // Task failed: check retry count TaskMetadata<?> metadata = taskMap.get(taskId); if (metadata != null && metadata.canRetry()) { metadata.incrementRetryCount(); // Resubmit the task completionService.submit(metadata.getTask()); } else { // Max retries reached: remove from map taskMap.remove(taskId); // Handle final failure } } } Thread.sleep(2000); // 2-second poll interval }
Pro Tip
Always remove completed/failed tasks from the map to prevent memory leaks, especially if your framework runs long-term. ConcurrentHashMap handles concurrent removals safely without blocking other operations.
内容的提问来源于stack exchange,提问作者Ranjith R Shenoy

