1

Every 5 minutes, within the 20th minute cycle, I need to retrieve the data. Currently, I'm using the map data structure.

Is there a better data structure? Every time I read and set the data, I have to write to the file to prevent program restart and data loss.

For example, if the initial data in the map is:

{-1:"result1",-2:"result2",-3:"result3",-4:"result4"}

I want to get the last -4 period's value which is "result4", and set the new value "result5", so that the updated map will be:

{-1:"result5",-2:"result1",-3:"result2",-4:"result3"}

And again, I want to get the last -4 period's value which is "result3", and set the new value "result6", so the map will be:

{-1:"result6",-2:"result5",-3:"result1",-4:"result2"}

The code:

private static String getAndSaveValue(int a) { 
    //read the map from file
    HashMap<Long,String> resultMap=getMapFromFile();
    String  value=resultMap.get(-4L);

    for (Long i = 4L; i >= 2; i--){
        resultMap.put(Long.parseLong(String.valueOf(i - 2 * i)),resultMap.get(1 - i));
    }
    resultMap.put(-1L,"result" + a);
    //save the map to file
    saveMapToFile(resultMap);

    return value;
}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
flower
  • 2,212
  • 3
  • 29
  • 44
  • It seems like your initial four results are reversed. I'd use a `List`. Append the new value to the end of the `List`, delete the value at position zero after the first four values, and write the four values to an output file. – Gilbert Le Blanc May 11 '22 at 13:47
  • Is the result data type actually a string, or a custom object? How frequent are the file read/writes? – Abhinav Mathur May 11 '22 at 14:12
  • @AbhinavMathur the rsult data type a custom object which contains time and resultMsg.Five minute one period – flower May 11 '22 at 14:24

2 Answers2

1

Based on your requirement, I think LinkedList data structure will be suitable for your requirement:

public class Test {
    public static void main(String[] args) {        
        LinkedList<String> ls=new LinkedList<String>();
        ls.push("result4");
        ls.push("result3");
        ls.push("result2");
        ls.push("result1");
        System.out.println(ls);
        ls.push("result5"); //pushing new value
        System.out.println("Last value:"+ls.pollLast()); //this will return `result4`
        System.out.println(ls);
        ls.push("result6"); //pushing new value
        System.out.println("Last value:"+ls.pollLast());  // this will give you `result3`
        System.out.println(ls);
    }
}

Output:

[result1, result2, result3, result4]
Last value:result4
[result5, result1, result2, result3]
Last value:result3  
[result6, result5, result1, result2]
Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
  • I find that BlockQueue may be also fit, it that right? – flower May 11 '22 at 14:26
  • @flower, yeah, it can also be used if your requirement needs to `wait` for this data structure to become non-empty for retrieval & empty / partial-empty for insertion. – Ashish Patil May 11 '22 at 14:32
  • & also if your data structure needs to have pre-defined capacity, then instead of `LinkedList` you might want to use any implementation of `BlockingQueue` which gives you option of setting initial capacity during initialization. – Ashish Patil May 11 '22 at 14:47
  • @flower It's not advisable to use *concurrent collections* in a single-threaded environment. The better approach will be to wrap the existing general purpose collection with a class in order to impose restrictions on the maximum size of the collection. – Alexander Ivanchenko May 11 '22 at 23:22
  • @Ashish Patili,Can queue or LinkedList put null object ?My be my object is null. – flower May 16 '22 at 07:54
  • @flower , `LinkedList` works well with `null`. I just tried doing `add` & `push` operations, & I can see there is no issue with adding null. – Ashish Patil May 17 '22 at 14:07
1

Judging by your example, you need a FIFO data structure which has a bounded size.

There's no bounded general purpose implementation of the Queue interface in the JDK. Only concurrent implementation could be bounded in size. But if you're not going to use it in a multithreaded environment, it's not the best choice because thread safety doesn't come for free - concurrent collections are slower, and also can create confusing for the reader of your code.

To achieve your goal, I suggest you to use the composition by wrapping ArrayDeque, which is an array-based implementation of the Queue and performs way better than LinkedList.

Note that is a preferred approach not to extend ArrayDeque (IS A relationship) and override its methods add() and offer(), but include it in a class as a field (HAS A relationship), so that all the method calls on the instance of your class will be forwarded to the underlying collection. You can find more information regarding this approach in the item "Favor composition over inheritance" of Effective Java by Joshua Bloch.

public class BoundQueue<T> {
    private Queue<T> queue;
    private int limit;
    
    public BoundQueue(int limit) {
        this.queue = new ArrayDeque<>(limit);
        this.limit = limit;
    }
    
    public void offer(T item) {
        if (queue.size() == limit) {
            queue.poll(); // or throw new IllegalStateException() depending on your needs
        }
        queue.add(item);
    }
    
    public T poll() {
        return queue.poll();
    }
    
    public boolean isEmpty() {
        return queue.isEmpty();
    }
}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • ,Can queue or LinkedList put null object ?My be my object is null. – flower May 16 '22 at 07:55
  • @flower Firstly, you have to distinguish between interface and implementation. See https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface `Queue` is an interface, `LinkedList` is an implementation of the `Queue` and `List`. Regarding the question about `null`, `LinkedList` is the only implementation of the `Queue` which allow `null` values. Why others disallow? Because `Queue` interface offers handy methods that allow to loop up at the first element of the queue without checking if the queue not is empty, `null` is used to indicate the absents of data. – Alexander Ivanchenko May 23 '22 at 11:50
  • @flower ... When `null` is considered to be a valid value in a queue it's impossible to distinguish between the cases when the queue is empty and the first value is `null`. And it generally a good practice to avoid using `null` in collections, because you can not extract any useful information from it. If `null` has a special meaning in your business logic that a design flaw. If you want your code to be clear and maintainable, you should design your system treating `null` as a special case, passing `null` arguments and storing `null` values. There are many ways how to approach that. – Alexander Ivanchenko May 23 '22 at 12:07
  • @flower ... It's hard to target a problem without knowing the details. For instance if you need to perform a default set of actions when there's no data, in place of using `null` you might consider implementing the *Null-object pattern*. – Alexander Ivanchenko May 23 '22 at 12:11