java.util.ConcurrentModificationException: concurrent access to hashmap - java

In an implementation, i have written the following code. The try-catch block is in a method
try{
InputVals iv = task.getInputVals();
Map<String, String> map = iv.getAllValues();
String a = map.get("value1");
String b = map.get("value2");
String x = funcxy.methodGetX();
String y = funcxy.methodGetY();
iv.setValue(xval, x);
iv.setValue(yval,y);
String []names = {"name1", "name2", "name3"}
for(int i = 0; i<names.length; i++ ){
iv.setValue("name"+i, names[i] );
}
}
When I make concurrent request few times (not always) it throws "java.util.ConcurrentModificationException: concurrent access to hashmap" error. I tried using
Map<String, String> map= new ConcurrentHashMap<String, String>();
map = iv.getAllValues();
But this didnt solve the issue. Can you help me out and let me know where I'm making the mistake. I cannot change the implementation of
InputVals iv = task.getInputVals();

I'm not entirely sure what you are trying to achieve, but as others have already pointed out, you likely have multiple threads trying to manipulate the map returned by iv.getAllValues() at the same time, hence throwing the exception.
Copying the map with a ConcurrentHashMap will work as you would be working off a local copy. However keep in mind that in doing so, you would be using it locally only, and consequently not need the concurrency checking that it provides. The problem with your code is that you do not actually copy the data to your new map. You would have needed to do:
Map<String, String> map= new ConcurrentHashMap<String, String>( iv.getAllValues() );
Depending on your needs when making the modifications to the map entries, the simplest & fastest would probably copy the map and work off a local copy. This will prevent any concurrency issues. Of course, if the other threads need access to your updated information, this plan does not work.
try{
InputVals iv = task.getInputVals();
Map<String, String> map = new HashMap<String, String>();
// copy all map values to a local var
map.putAll( iv.getAllValues() );
String a = map.get("value1");
String b = map.get("value2");
String x = funcxy.methodGetX();
String y = funcxy.methodGetY();
iv.setValue(xval, x);
iv.setValue(yval,y);
String []names = {"name1", "name2", "name3"}
for(int i = 0; i<names.length; i++ ){
iv.setValue("name"+i, names[i] );
}
}
Short of this, you would need to ensure that any calls to the map are made in synchronized blocks. However, this can be extremely difficult and tedious if you have several different places in the code where you access this map.

You have to synchronize all access to the Map returned by the getInputVals(). It is being altered somewhere in a separate thread. You will need something along the lines of the code below, but what is also very important is that the lockObj must also be applied everywhere else that this map is being used, including wherever it is currently being modified (this code has not been shown).
try{
InputVals iv = task.getInputVals();
String a;
String b;
synchronized (lockOjb) {
Map<String, String> map = iv.getAllValues();
a = map.get("value1");
b = map.get("value2");
}
String x = funcxy.methodGetX();
String y = funcxy.methodGetY();
iv.setValue(xval, x);
iv.setValue(yval,y);
String []names = {"name1", "name2", "name3"}
for(int i = 0; i<names.length; i++ ){
iv.setValue("name"+i, names[i] );
}
}
This may or may not be possible, depending on whether you have the ability to change this code. If it is already happening within a library, for instance, you may simply have to redesign your code so that it is not multithreaded, at least anywhere where this map is accessed.

What does your InputVals.setValue() does? How is it defined? there is no use if you define ConcurrentHashMap in the business logic as you are using the reference of original variable. You would need to take care in the actual bean itself.
If it some thing like below
Class Inputvals {
Map<String, String> map = new HashMap <String,String>();
public void setValue(String a,String b){
map.put(a,b);
}
public Map<String,String> getAllValues(){
return map;
}
}
I suggest you to change as below
Class Inputvals {
Map<String, String> map = new ConcurrentHashMap<String,String>();
public void setValue(String a,String b){
map.put(a,b);
}
..
...
this should help you to resolve multi threaded access issue.

You may need to wrap your map in a Synchronized collection
Map<String, String> map = Collections.synchronizedMap(iv.getAllValues());
Then go ahead and access your map.

Related

Check is HashMap contains another HashMap with specific value in Java

I have a HashMap like this:
private HashMap<Integer, HashMap<String, Material>> logs = new HashMap<>();
Then I have multiple Materials stored as enum (for example. Material.OAK_LOG).
Is there any easy way to check if HashMap logs contains HashMap with specific Material?
I came up with this, which works, but I want to know if there is any other way to do this without looping through the entire HashMap
private boolean hasLog(Material mat){
boolean contains = false;
for (Map.Entry<Integer, HashMap<String, Material>> entry : this.logs.entrySet()) {
if(entry.getValue().containsValue(mat)){
contains = true;
break;
}
}
return contains;
}
No, you have to loop through the maps, doing sequential search.
You can simplify the logic a little by using values() instead of entrySet(), and simply return directly, but that's just minor refactoring:
private boolean hasLog(Material mat) {
for (HashMap<String, Material> submap : this.logs.values())
if (submap.containsValue(mat))
returns true;
return false;
}
You can write the same logic using Java 8+ Streams, but it is the same nested loop sequential search, so runtime complexity remains O(nm).
private boolean hasLog(Material mat) {
return this.logs.values().stream()
.anyMatch(submap -> submap.containsValue(mat));
}
If your Material objects are immutable and unique from an equals perspective, you could use them as a key in a cross reference map. But if Material will change, your maps could get corrupted depending on how equals is set up.
Map<Material, String> crossRef = new HashMap<>();
Whenever you add a new Map with a material to logs, do the following:
int outerKey; = ... // some integer to get the inner map
String innerKey = .. // some string to get the actual Material
Map<String, Material> innerMap = logs.get(outerKey);
Material mat = new Material(...);
innerMap.put(innerKey, mat);
crossRef.put(mat, outerKey+"_"+innerKey);
Then later
if (crossRef.contains(mat)) {
// it exists somewhere.
String mapId = crossRef.get(mat);
key[] parts = mapId.split("_");
int outerKey = Integer.valueOf(parts[0]);
String innerKey = parts[1];
Map<String, Material> map = logs.get(outerKey);
Material mat = map.get(innerKey);
}
One other downside is that your speeding up lookup time at the cost of more storage.
And to re-emphasize if two different Material objects compare equally they will be considered duplicates and thus cannot be used as keys to access both types of material.
Instead of using a concatenated String as the cross-ref key you could use a simple class or record that holds those as their specific type.
This was a drawn out answer to a simple question but it may provide some alternative ideas as to how to address your problem.

Is there a Map object with takes index and key and object? Java

I'm trying to emulate a rotor of an enigma machine in Java.
I need an object which takes an index, a key and an object, because I unsuccessfully tried HashMaps like this:
private HashMap<Integer,Integer> rotorWiring = new HashMap<Integer, Integer();
private HashMap<Integer,Integer> reverseRotorWiring = new HashMap<Integer, Integer>();
//The "wiring" of the rotor is set from a String,
public void setRotorWiring(String Wiring) {
if (Wiring.length()==26) {
for (int i=0; i<Wiring.length();i++ ) {
char tempChar = Wiring.charAt(i);
int valueOfChar = (int)tempChar-64;
if (valueOfChar<=26){
this.rotorWiring.put(i+1,valueOfChar);
this.reverseRotorWiring.put(valueOfChar,i+1);
}
}
}
}
So far so good, this allows me to translate e.x. an A to an E, however, once I tried to simulate a turn of the rotor like this:
//It should be mentioned that I designing the program to only accept characters a to z inclusive.
public void turn() {
for (int i=1;i<=rotorWiring.size();i++) {
if (i!=26) {
rotorWiring.replace(i, rotorWiring.get(i+1));
}
else {
rotorWiring.replace(i, rotorWiring.get(1));
}
}
for (int i=1;i<=rotorWiring.size();i++) {
if (i!=26) {
reverseRotorWiring.replace(i, rotorWiring.get(i+1));
}
}
}
However, I noticed that this rather simulates an offset of the internal wiring of the rotor rather than a turn... I'm asking for a "Map"-like solutions with an index, key and object, because that would allow me to offset the index of all the keys and objects by 1, thus simulating a turn.
I am, however, open to suggestions for different solutions to this problem.
It should be mentioned that I'm a bit of a novice, and therefore appreciate rather in-depth explanations.
Many thanks.
Welcome to StackOverflow. There doesn't exist an implementation of what you have described in JDK. However, there are more ways to achieve the storing of Integer-String-Object. Note that both the index and the key are unique by definition. Also, note that the index-key are tightly coupled. You might want to put a Map to another Map:
Map<Integer, Map<String, MyObject>> map;
Or use a collection characteristic for indices:
List<Map<String, MyObject>>
Be careful with removing items which change the index of all the subsequent elements - replace it with null instead to keep the indices. Alternatively, you can create a decorator for your defined object with index/key:
Map<Integer, MyDecoratedObject> map;
Where the MyDecoratedObject would look like:
public class MyDecoratedObject {
private final String key; // or int index
private final MyObject delegate;
// Full-args constructor, getters
}
Finally, it's up to you to pick a way that satisfied your requirements the most.
A map of maps was the solution! It was solved like this:
private HashMap<Integer,HashMap<Integer,Integer>> rotorWiring = new HashMap<Integer, HashMap<Integer,Integer>>();
private HashMap<Integer,HashMap<Integer,Integer>> reverseRotorWiring = new HashMap<Integer, HashMap<Integer,Integer>>();
public void setRotorWiring(String Wiring) {
if (Wiring.length()==26) {
for (int i=0; i<Wiring.length();i++ ) {
HashMap<Integer, Integer> wire = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> reverseWire = new HashMap<Integer, Integer>();
char tempChar = Wiring.charAt(i);
int valueOfChar = (int)tempChar-64;
if (valueOfChar<=26){
wire.put(i+1,valueOfChar);
reverseWire.put(valueOfChar,i+1);
rotorWiring.put(i, wire);
reverseRotorWiring.put(i, reverseWire);
}
}
}
}

Iterate over a HashMap with multiple values per key

I am currently learning sets and maps through university (still using Java 7).
They have given us a half finished to-do list app to complete. Currently the to-do list takes three String local variables to allow the user to state a job (aJob), a time to do it (aTime) and a date to do it (aDate).
The app also has an instance variable (today) that holds todays date.
I need to come up with a way to check the HashMap for any tasks that are due today. So I need to be able to query just the HashMap values attributed by the aDate local variable.
I know that to iterate Maps that I can place the keys or the values into a Set and then iterate over the set - not a problem. But if I use the values() method (within the Map class) to put these into a set - it places all three Strings per key into the set. I just want to move the aDate values into a set.
Any ideas?
I only seem to be able to find examples where the Maps have just a single Key and Single Value. This list has a single key and three values per key.
Any pointers would be good?
Kind Regards
Edit.....
Just thought I would add some code to help as there have been several different approaches - which I am all very greatful for. But not sure if they suit my needs....
The Job Class is constructed as such...
public Job(String aJob, String aDate, String aTime)
{
Job = aJob;
date = aDate;
time = aTime;
}
I then create the map within the instance declarations for the To Do List class....
Map<Integer, Job> toDoList = new HashMap<>();
So I need to know the best way to iterate over this map, but it is only the Job attribute 'aDate' that is possibly going to hold the value I am after.
Not sure if that helps at all?
Kind Regards
If really the only structure you're allowed to use is a Map where each key has 3 values (which is the case if I understand correctly), of which only one is a Date, you technically could do the following:
map.values()
.stream()
.filter(Date.class::isInstance)
...whatever else you want to do
The other suggested solutions are far better though, design wise.
If you can't use a custom class, as suggested by Toisen, maybe HashMap<String, HashMap<String, ArrayList<String>>> could do the trick for you.
I've added a sample of how to use it (as well as populating it with some random data)
public class FunkyMap {
private HashMap<String, HashMap<String, ArrayList<String>>> jobs;
// For random data
private String[] job = {"EAT", "SLEEP", "FART", "RELAX", "WORK"};
private String[] time = {"MORNING", "BEFORENOON", "NOON", "AFTERNOON", "EVENING", "MIDNIGHT"};
private String[] date = {"FIRST", "SECOND", "THIRD", "FOURTH"};
public FunkyMap() {
jobs = new HashMap<>();
// To populate some random data
Random r = new Random();
for(int i = 0; i < 20; i++) {
String d = date[r.nextInt(date.length)];
if(jobs.containsKey(d)) {
HashMap<String, ArrayList<String>> inner = jobs.get(d);
String t = time[r.nextInt(time.length)];
if(inner.containsKey(t)) {
inner.get(t).add(job[r.nextInt(job.length)]);
} else {
List<String> s = Arrays.asList(new String(job[r.nextInt(job.length)]));
inner.put(t, new ArrayList<String>(s));
}
} else {
jobs.put(d, new HashMap<String, ArrayList<String>>());
}
}
// Actual iteration over date => time => jobs
Iterator<String> i = jobs.keySet().iterator();
while(i.hasNext()) {
String iKey = i.next();
HashMap<String, ArrayList<String>> inner = jobs.get(iKey);
System.out.println("Jobs scheduled for " + iKey);
Iterator<String> j = inner.keySet().iterator();
while(j.hasNext()) {
String jKey = j.next();
ArrayList<String> actualJobs = inner.get(jKey);
System.out.println("\tAt " + jKey);
for(String s : actualJobs) {
System.out.println("\t\tDo " + s);
}
}
}
}
public static void main(String[] args) {
new FunkyMap();
}
}
I took the liberty to assume that dates were unique, and time was unique per date, while a time could hold any number of jobs including duplicates. If the last assumption with jobs is not true, you could swap ArrayList<String> with Set<String>.
Just create a class that holds all data that you need. E.g.
If you need something strange like Map<String, Tuple<String, Integer, Date>> just make a new class that holds the Tuple:
class TupleHolder {
private String firstValue;
private Integer secondValue;
private Date thirdValue;
// get/set here...
}
and use it: Map<String, TupleHolder>

Thread-safe way of incrementing value for specific key in a map inside another map

So, I have one map inside another one, for example, it might be word-counter per account base:
Map<Long, Map<String, Long>>
What is proper thread-safe way to increment the counter?
I guess it's possible to use ConcurrentHashMap and LongAdder like following:
private Map<Long, Map<GovernorLimitName, LongAdder>> status = new ConcurrentHashMap<> ();
public void count (Long accountId, String word) {
status.putIfAbsent (accountId, new ConcurrentHashMap<GovernorLimitName, LongAdder> ());
synchronized (getStatus ().get (accountId)) {
getStatus ().get (accountId).computeIfAbsent(limitName, k -> new LongAdder()).increment();
}
}
I believe that syncronyzation here is required cause of race condition between getting inner map and performing comuteIfAbsent() on it, is that correct?
Updated
I assume that both submaps and adders might be removed, cause there might be other methods accessing that map.
There's no point in using ConcurrentHashMap if you need to synchronize and you're right that you do because you're getting the value: Map<GovernorLimitName, LongAdder> (which is done concurrently) and then fetch LongAdder and increment it (which is not).
Instead of using Long use AtomicLong and change the implementation to use a regular HashMap.
You don't need the synchronized, as long as submaps are never removed from status, and adders are never removed from the submaps.
Creating a new ConcurrentHashMap that you will usually throw away is too expensive, though. Using the data structures you already have, you can do it like this:
public void count (Long accountId, GovernorLimitName limitName) {
Map<GovernorLimitName, LongAdder> submap = status.computeIfAbsent(accountId,
a -> new ConcurrentHashMap<GovernorLimitName, LongAdder> ());
LongAdder adder = submap.computeIfAbsent(limitName, k -> new LongAdder());
adder.incremeent();
}
instead of using putIfAbsent on main map, just use compute function (and do everything inside that function, even the inner map stuff). Whatever you do inside the function will be thread-safe if using ConcurrentHashMap in the root map; no need for synchronization block if you do it this way.
obviously, you will still need concurrenthashmap with this approach (in both) since i guess you will be doing gets at some other point of your code, and otherwise you would have concurrency issues while reading data.
other approaches could be taken instead of using ConcurrentHashMap's, but that's out of the scope of the question and it's fine to use those implementations.
Here you have some code (might have typos, and codestyle can be improved):
private Map<Long, Map<GovernorLimitName, LongAdder>> status = new ConcurrentHashMap<> ();
public void count (Long accountId, String word) {
status.compute(accountId, (k, v) -> {
if (v == null) {
v = new ConcurrentHashMap<>();
}
v.compute(limitName, (k2, v2) -> {
if (v2 == null) {
v2 = new LongAdder();
}
v2.increment();
return v2;
});
return v;
});
}

Search multiple HashMaps at the same time

tldr: How can I search for an entry in multiple (read-only) Java HashMaps at the same time?
The long version:
I have several dictionaries of various sizes stored as HashMap< String, String >. Once they are read in, they are never to be changed (strictly read-only).
I want to check whether and which dictionary had stored an entry with my key.
My code was originally looking for a key like this:
public DictionaryEntry getEntry(String key) {
for (int i = 0; i < _numDictionaries; i++) {
HashMap<String, String> map = getDictionary(i);
if (map.containsKey(key))
return new DictionaryEntry(map.get(key), i);
}
return null;
}
Then it got a little more complicated: my search string could contain typos, or was a variant of the stored entry. Like, if the stored key was "banana", it is possible that I'd look up "bannana" or "a banana", but still would like the entry for "banana" returned. Using the Levenshtein-Distance, I now loop through all dictionaries and each entry in them:
public DictionaryEntry getEntry(String key) {
for (int i = 0; i < _numDictionaries; i++) {
HashMap<String, String> map = getDictionary(i);
for (Map.Entry entry : map.entrySet) {
// Calculate Levenshtein distance, store closest match etc.
}
}
// return closest match or null.
}
So far everything works as it should and I'm getting the entry I want. Unfortunately I have to look up around 7000 strings, in five dictionaries of various sizes (~ 30 - 70k entries) and it takes a while. From my processing output I have the strong impression my lookup dominates overall runtime.
My first idea to improve runtime was to search all dictionaries parallely. Since none of the dictionaries is to be changed and no more than one thread is accessing a dictionary at the same time, I don't see any safety concerns.
The question is just: how do I do this? I have never used multithreading before. My search only came up with Concurrent HashMaps (but to my understanding, I don't need this) and the Runnable-class, where I'd have to put my processing into the method run(). I think I could rewrite my current class to fit into Runnable, but I was wondering if there is maybe a simpler method to do this (or how can I do it simply with Runnable, right now my limited understanding thinks I have to restructure a lot).
Since I was asked to share the Levenshtein-Logic: It's really nothing fancy, but here you go:
private int _maxLSDistance = 10;
public Map.Entry getClosestMatch(String key) {
Map.Entry _closestMatch = null;
int lsDist;
if (key == null) {
return null;
}
for (Map.Entry entry : _dictionary.entrySet()) {
// Perfect match
if (entry.getKey().equals(key)) {
return entry;
}
// Similar match
else {
int dist = StringUtils.getLevenshteinDistance((String) entry.getKey(), key);
// If "dist" is smaller than threshold and smaller than distance of already stored entry
if (dist < _maxLSDistance) {
if (_closestMatch == null || dist < _lsDistance) {
_closestMatch = entry;
_lsDistance = dist;
}
}
}
}
return _closestMatch
}
In order to use multi-threading in your case, could be something like:
The "monitor" class, which basically stores the results and coordinates the threads;
public class Results {
private int nrOfDictionaries = 4; //
private ArrayList<String> results = new ArrayList<String>();
public void prepare() {
nrOfDictionaries = 4;
results = new ArrayList<String>();
}
public synchronized void oneDictionaryFinished() {
nrOfDictionaries--;
System.out.println("one dictionary finished");
notifyAll();
}
public synchronized boolean isReady() throws InterruptedException {
while (nrOfDictionaries != 0) {
wait();
}
return true;
}
public synchronized void addResult(String result) {
results.add(result);
}
public ArrayList<String> getAllResults() {
return results;
}
}
The Thread it's self, which can be set to search for the specific dictionary:
public class ThreadDictionarySearch extends Thread {
// the actual dictionary
private String dictionary;
private Results results;
public ThreadDictionarySearch(Results results, String dictionary) {
this.dictionary = dictionary;
this.results = results;
}
#Override
public void run() {
for (int i = 0; i < 4; i++) {
// search dictionary;
results.addResult("result of " + dictionary);
System.out.println("adding result from " + dictionary);
}
results.oneDictionaryFinished();
}
}
And the main method for demonstration:
public static void main(String[] args) throws Exception {
Results results = new Results();
ThreadDictionarySearch threadA = new ThreadDictionarySearch(results, "dictionary A");
ThreadDictionarySearch threadB = new ThreadDictionarySearch(results, "dictionary B");
ThreadDictionarySearch threadC = new ThreadDictionarySearch(results, "dictionary C");
ThreadDictionarySearch threadD = new ThreadDictionarySearch(results, "dictionary D");
threadA.start();
threadB.start();
threadC.start();
threadD.start();
if (results.isReady())
// it stays here until all dictionaries are searched
// because in "Results" it's told to wait() while not finished;
for (String string : results.getAllResults()) {
System.out.println("RESULT: " + string);
}
I think the easiest would be to use a stream over the entry set:
public DictionaryEntry getEntry(String key) {
for (int i = 0; i < _numDictionaries; i++) {
HashMap<String, String> map = getDictionary(i);
map.entrySet().parallelStream().foreach( (entry) ->
{
// Calculate Levenshtein distance, store closest match etc.
}
);
}
// return closest match or null.
}
Provided you are using java 8 of course. You could also wrap the outer loop into an IntStream as well. Also you could directly use the Stream.reduce to get the entry with the smallest distance.
Maybe try thread pools:
ExecutorService es = Executors.newFixedThreadPool(_numDictionaries);
for (int i = 0; i < _numDictionaries; i++) {
//prepare a Runnable implementation that contains a logic of your search
es.submit(prepared_runnable);
}
I believe you may also try to find a quick estimate of strings that completely do not match (i.e. significant difference in length), and use it to finish your logic ASAP, moving to next candidate.
I have my strong doubts that HashMaps are a suitable solution here, especially if you want to have some fuzzing and stop words. You should utilize a proper full text search solutions like ElaticSearch or Apache Solr or at least an available engine like Apache Lucene.
That being said, you can use a poor man's version: Create an array of your maps and a SortedMap, iterate over the array, take the keys of the current HashMap and store them in the SortedMap with the index of their HashMap. To retrieve a key, you first search in the SortedMap for said key, get the respective HashMap from the array using the index position and lookup the key in only one HashMap. Should be fast enough without the need for multiple threads to dig through the HashMaps. However, you could make the code below into a runnable and you can have multiple lookups in parallel.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
public class Search {
public static void main(String[] arg) {
if (arg.length == 0) {
System.out.println("Must give a search word!");
System.exit(1);
}
String searchString = arg[0].toLowerCase();
/*
* Populating our HashMaps.
*/
HashMap<String, String> english = new HashMap<String, String>();
english.put("banana", "fruit");
english.put("tomato", "vegetable");
HashMap<String, String> german = new HashMap<String, String>();
german.put("Banane", "Frucht");
german.put("Tomate", "Gemüse");
/*
* Now we create our ArrayList of HashMaps for fast retrieval
*/
List<HashMap<String, String>> maps = new ArrayList<HashMap<String, String>>();
maps.add(english);
maps.add(german);
/*
* This is our index
*/
SortedMap<String, Integer> index = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
/*
* Populating the index:
*/
for (int i = 0; i < maps.size(); i++) {
// We iterate through or HashMaps...
HashMap<String, String> currentMap = maps.get(i);
for (String key : currentMap.keySet()) {
/* ...and populate our index with lowercase versions of the keys,
* referencing the array from which the key originates.
*/
index.put(key.toLowerCase(), i);
}
}
// In case our index contains our search string...
if (index.containsKey(searchString)) {
/*
* ... we find out in which map of the ones stored in maps
* the word in the index originated from.
*/
Integer mapIndex = index.get(searchString);
/*
* Next, we look up said map.
*/
HashMap<String, String> origin = maps.get(mapIndex);
/*
* Last, we retrieve the value from the origin map
*/
String result = origin.get(searchString);
/*
* The above steps can be shortened to
* String result = maps.get(index.get(searchString).intValue()).get(searchString);
*/
System.out.println(result);
} else {
System.out.println("\"" + searchString + "\" is not in the index!");
}
}
}
Please note that this is a rather naive implementation only provided for illustration purposes. It doesn't address several problems (you can't have duplicate index entries, for example).
With this solution, you are basically trading startup speed for query speed.
Okay!!..
Since your concern is to get faster response.
I would suggest you to divide the work between threads.
Lets you have 5 dictionaries May be keep three dictionaries to one thread and rest two will take care by another thread.
And then witch ever thread finds the match will halt or terminate the other thread.
May be you need an extra logic to do that dividing work ... But that wont effect your performance time.
And may be you need little more changes in your code to get your close match:
for (Map.Entry entry : _dictionary.entrySet()) {
you are using EntrySet But you are not using values anyway it seems getting entry set is a bit expensive. And I would suggest you to just use keySet since you are not really interested in the values in that map
for (Map.Entry entry : _dictionary.keySet()) {
For more details on the proformance of map Please read this link Map performances
Iteration over the collection-views of a LinkedHashMap requires time proportional to the size of the map, regardless of its capacity. Iteration over a HashMap is likely to be more expensive, requiring time proportional to its capacity.

Categories