Why does checking if a HashMap has a certain value take very long to execute within a for loop?












4














I am working with meet-in-the-middle attack on Double-DES. I have implemented the DES encryption/decryption and done the encryptions and now I would like to perform a MITM attack on the Double-DES in order to find the keys. The way I am trying to achieve this is by storing, within a for loop, the intermediate ciphers as the key of a HashMap and the possible keys as the values of the HashMap. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have an if statement, which checks whether the possible key already exists in the HashMap. If not, then it uses it to encrypt the plain text and store the cipher text and the possible key in the HashMap. Aftwards, I try to find the keys, which have matching intermediate cipher text by iterating through the HashMap with a foreach and compare each intermediate cipher text from the encryptions with the intermediate cipher text from the decryptions.



However, I am unable to find the match as it takes too long to finish. I have been waiting for like 2 hours now without any result. If I remove the if statement, which checks if the possible key is already in the HashMap it finishes in like 10 seconds.



for (int size = intermediateCipher.size(); size < Math.pow(2, 20); size++) { // intermediateCipher is my HashMap consisting of <String, byte>
byte possibleKey = generateDesKey(); // generateDesKey generates a key of 64 bits
if (!intermediateCipher.containsValue(possibleKey)) {
intermediateCipher.put((encrypt(possibleKey, plainText)).toString(), possibleKey);
}
}

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = (decrypt(arr.getValue(), cipherText)).toString();

if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I should mention that only 20 bits of the DES key is effective. That is why there are 2^20 possible keys. Furthermore, if I don't have the if statement, which checks if the possible key is already in the HashMap, I get 510 matches, which is too much.



UPDATE:



I have tried using a Set in order to store the keys first and then used the keys from the Set to encrypt etc. However, instead of having a for, which iterates from 0 to 2^20, I have tried with a while loop, which checks iterates as long as the Set has elements. However, I have tried running this approach for over 10 mins without any result. It never gets out of the loop.



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());

for (int i = 0; i < possibleKeySet.size(); i++) {

intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(),
possibleKeySet.iterator().next());
}

System.out.println("ss " + intermediateCipher.size());

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = ((decrypt(arr.getValue(), cipherText)).toString());
if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I have read that for a set hasNext() always returns true for a non-empty collection. So, I have tried with a for each, but the size of the hashMap is never the same as the size of the set of keys, which doesn't make sense to me as I use every key in the set:



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}

System.out.println(possibleKeySet.size());

for (byte key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(),
key);
}









share|improve this question
























  • if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
    – Peter Lawrey
    Nov 22 at 17:55












  • I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
    – Elliott Frisch
    Nov 22 at 17:55










  • @PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
    – Bab
    Nov 22 at 17:57










  • @Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
    – Peter Lawrey
    Nov 22 at 17:58






  • 1




    The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
    – John Bollinger
    Nov 22 at 18:02


















4














I am working with meet-in-the-middle attack on Double-DES. I have implemented the DES encryption/decryption and done the encryptions and now I would like to perform a MITM attack on the Double-DES in order to find the keys. The way I am trying to achieve this is by storing, within a for loop, the intermediate ciphers as the key of a HashMap and the possible keys as the values of the HashMap. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have an if statement, which checks whether the possible key already exists in the HashMap. If not, then it uses it to encrypt the plain text and store the cipher text and the possible key in the HashMap. Aftwards, I try to find the keys, which have matching intermediate cipher text by iterating through the HashMap with a foreach and compare each intermediate cipher text from the encryptions with the intermediate cipher text from the decryptions.



However, I am unable to find the match as it takes too long to finish. I have been waiting for like 2 hours now without any result. If I remove the if statement, which checks if the possible key is already in the HashMap it finishes in like 10 seconds.



for (int size = intermediateCipher.size(); size < Math.pow(2, 20); size++) { // intermediateCipher is my HashMap consisting of <String, byte>
byte possibleKey = generateDesKey(); // generateDesKey generates a key of 64 bits
if (!intermediateCipher.containsValue(possibleKey)) {
intermediateCipher.put((encrypt(possibleKey, plainText)).toString(), possibleKey);
}
}

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = (decrypt(arr.getValue(), cipherText)).toString();

if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I should mention that only 20 bits of the DES key is effective. That is why there are 2^20 possible keys. Furthermore, if I don't have the if statement, which checks if the possible key is already in the HashMap, I get 510 matches, which is too much.



UPDATE:



I have tried using a Set in order to store the keys first and then used the keys from the Set to encrypt etc. However, instead of having a for, which iterates from 0 to 2^20, I have tried with a while loop, which checks iterates as long as the Set has elements. However, I have tried running this approach for over 10 mins without any result. It never gets out of the loop.



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());

for (int i = 0; i < possibleKeySet.size(); i++) {

intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(),
possibleKeySet.iterator().next());
}

System.out.println("ss " + intermediateCipher.size());

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = ((decrypt(arr.getValue(), cipherText)).toString());
if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I have read that for a set hasNext() always returns true for a non-empty collection. So, I have tried with a for each, but the size of the hashMap is never the same as the size of the set of keys, which doesn't make sense to me as I use every key in the set:



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}

System.out.println(possibleKeySet.size());

for (byte key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(),
key);
}









share|improve this question
























  • if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
    – Peter Lawrey
    Nov 22 at 17:55












  • I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
    – Elliott Frisch
    Nov 22 at 17:55










  • @PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
    – Bab
    Nov 22 at 17:57










  • @Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
    – Peter Lawrey
    Nov 22 at 17:58






  • 1




    The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
    – John Bollinger
    Nov 22 at 18:02
















4












4








4


1





I am working with meet-in-the-middle attack on Double-DES. I have implemented the DES encryption/decryption and done the encryptions and now I would like to perform a MITM attack on the Double-DES in order to find the keys. The way I am trying to achieve this is by storing, within a for loop, the intermediate ciphers as the key of a HashMap and the possible keys as the values of the HashMap. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have an if statement, which checks whether the possible key already exists in the HashMap. If not, then it uses it to encrypt the plain text and store the cipher text and the possible key in the HashMap. Aftwards, I try to find the keys, which have matching intermediate cipher text by iterating through the HashMap with a foreach and compare each intermediate cipher text from the encryptions with the intermediate cipher text from the decryptions.



However, I am unable to find the match as it takes too long to finish. I have been waiting for like 2 hours now without any result. If I remove the if statement, which checks if the possible key is already in the HashMap it finishes in like 10 seconds.



for (int size = intermediateCipher.size(); size < Math.pow(2, 20); size++) { // intermediateCipher is my HashMap consisting of <String, byte>
byte possibleKey = generateDesKey(); // generateDesKey generates a key of 64 bits
if (!intermediateCipher.containsValue(possibleKey)) {
intermediateCipher.put((encrypt(possibleKey, plainText)).toString(), possibleKey);
}
}

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = (decrypt(arr.getValue(), cipherText)).toString();

if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I should mention that only 20 bits of the DES key is effective. That is why there are 2^20 possible keys. Furthermore, if I don't have the if statement, which checks if the possible key is already in the HashMap, I get 510 matches, which is too much.



UPDATE:



I have tried using a Set in order to store the keys first and then used the keys from the Set to encrypt etc. However, instead of having a for, which iterates from 0 to 2^20, I have tried with a while loop, which checks iterates as long as the Set has elements. However, I have tried running this approach for over 10 mins without any result. It never gets out of the loop.



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());

for (int i = 0; i < possibleKeySet.size(); i++) {

intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(),
possibleKeySet.iterator().next());
}

System.out.println("ss " + intermediateCipher.size());

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = ((decrypt(arr.getValue(), cipherText)).toString());
if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I have read that for a set hasNext() always returns true for a non-empty collection. So, I have tried with a for each, but the size of the hashMap is never the same as the size of the set of keys, which doesn't make sense to me as I use every key in the set:



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}

System.out.println(possibleKeySet.size());

for (byte key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(),
key);
}









share|improve this question















I am working with meet-in-the-middle attack on Double-DES. I have implemented the DES encryption/decryption and done the encryptions and now I would like to perform a MITM attack on the Double-DES in order to find the keys. The way I am trying to achieve this is by storing, within a for loop, the intermediate ciphers as the key of a HashMap and the possible keys as the values of the HashMap. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have an if statement, which checks whether the possible key already exists in the HashMap. If not, then it uses it to encrypt the plain text and store the cipher text and the possible key in the HashMap. Aftwards, I try to find the keys, which have matching intermediate cipher text by iterating through the HashMap with a foreach and compare each intermediate cipher text from the encryptions with the intermediate cipher text from the decryptions.



However, I am unable to find the match as it takes too long to finish. I have been waiting for like 2 hours now without any result. If I remove the if statement, which checks if the possible key is already in the HashMap it finishes in like 10 seconds.



for (int size = intermediateCipher.size(); size < Math.pow(2, 20); size++) { // intermediateCipher is my HashMap consisting of <String, byte>
byte possibleKey = generateDesKey(); // generateDesKey generates a key of 64 bits
if (!intermediateCipher.containsValue(possibleKey)) {
intermediateCipher.put((encrypt(possibleKey, plainText)).toString(), possibleKey);
}
}

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = (decrypt(arr.getValue(), cipherText)).toString();

if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I should mention that only 20 bits of the DES key is effective. That is why there are 2^20 possible keys. Furthermore, if I don't have the if statement, which checks if the possible key is already in the HashMap, I get 510 matches, which is too much.



UPDATE:



I have tried using a Set in order to store the keys first and then used the keys from the Set to encrypt etc. However, instead of having a for, which iterates from 0 to 2^20, I have tried with a while loop, which checks iterates as long as the Set has elements. However, I have tried running this approach for over 10 mins without any result. It never gets out of the loop.



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());

for (int i = 0; i < possibleKeySet.size(); i++) {

intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(),
possibleKeySet.iterator().next());
}

System.out.println("ss " + intermediateCipher.size());

int count = 0;
for (Entry<String, byte> arr : intermediateCipher.entrySet()) {

String temp = ((decrypt(arr.getValue(), cipherText)).toString());
if (intermediateCipher.containsKey(temp)) {
count++;
}
}


I have read that for a set hasNext() always returns true for a non-empty collection. So, I have tried with a for each, but the size of the hashMap is never the same as the size of the set of keys, which doesn't make sense to me as I use every key in the set:



for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}

System.out.println(possibleKeySet.size());

for (byte key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(),
key);
}






java performance hashmap des






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 at 21:08

























asked Nov 22 at 17:48









Bab

12910




12910












  • if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
    – Peter Lawrey
    Nov 22 at 17:55












  • I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
    – Elliott Frisch
    Nov 22 at 17:55










  • @PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
    – Bab
    Nov 22 at 17:57










  • @Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
    – Peter Lawrey
    Nov 22 at 17:58






  • 1




    The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
    – John Bollinger
    Nov 22 at 18:02




















  • if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
    – Peter Lawrey
    Nov 22 at 17:55












  • I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
    – Elliott Frisch
    Nov 22 at 17:55










  • @PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
    – Bab
    Nov 22 at 17:57










  • @Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
    – Peter Lawrey
    Nov 22 at 17:58






  • 1




    The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
    – John Bollinger
    Nov 22 at 18:02


















if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
– Peter Lawrey
Nov 22 at 17:55






if temp isn't used, you don't need to toString which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
– Peter Lawrey
Nov 22 at 17:55














I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55




I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55












@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57




@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57












@Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
– Peter Lawrey
Nov 22 at 17:58




@Bab I assumed if you removed the if you removed the intermediateCipher.containsKey(temp) but again, without the if this method call doesn't do anything either.
– Peter Lawrey
Nov 22 at 17:58




1




1




The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
– John Bollinger
Nov 22 at 18:02






The if statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey)), and the key is not a map key, but rather a cryptographic key stored as a map value.
– John Bollinger
Nov 22 at 18:02














2 Answers
2






active

oldest

votes


















1














Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:




Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.




To take advantage of a hash lookup you should check the keys with Map.containsKey():



if (!intermediateCipher.containsKey(possibleKey)) {
...
}





share|improve this answer





















  • So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
    – Bab
    Nov 22 at 18:12












  • @Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
    – Karol Dowbecki
    Nov 22 at 18:13












  • Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:31












  • Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
    – Bab
    Nov 22 at 19:29










  • Have been waiting for over 10 mins.
    – Bab
    Nov 22 at 19:30



















1














Map.containsValue() must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue() on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.



Consider instead keeping an auxiliary Set of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.






share|improve this answer





















  • By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:32










  • Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
    – Bab
    Nov 22 at 19:33











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436072%2fwhy-does-checking-if-a-hashmap-has-a-certain-value-take-very-long-to-execute-wit%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:




Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.




To take advantage of a hash lookup you should check the keys with Map.containsKey():



if (!intermediateCipher.containsKey(possibleKey)) {
...
}





share|improve this answer





















  • So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
    – Bab
    Nov 22 at 18:12












  • @Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
    – Karol Dowbecki
    Nov 22 at 18:13












  • Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:31












  • Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
    – Bab
    Nov 22 at 19:29










  • Have been waiting for over 10 mins.
    – Bab
    Nov 22 at 19:30
















1














Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:




Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.




To take advantage of a hash lookup you should check the keys with Map.containsKey():



if (!intermediateCipher.containsKey(possibleKey)) {
...
}





share|improve this answer





















  • So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
    – Bab
    Nov 22 at 18:12












  • @Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
    – Karol Dowbecki
    Nov 22 at 18:13












  • Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:31












  • Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
    – Bab
    Nov 22 at 19:29










  • Have been waiting for over 10 mins.
    – Bab
    Nov 22 at 19:30














1












1








1






Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:




Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.




To take advantage of a hash lookup you should check the keys with Map.containsKey():



if (!intermediateCipher.containsKey(possibleKey)) {
...
}





share|improve this answer












Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:




Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.




To take advantage of a hash lookup you should check the keys with Map.containsKey():



if (!intermediateCipher.containsKey(possibleKey)) {
...
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 22 at 18:08









Karol Dowbecki

16.4k82849




16.4k82849












  • So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
    – Bab
    Nov 22 at 18:12












  • @Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
    – Karol Dowbecki
    Nov 22 at 18:13












  • Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:31












  • Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
    – Bab
    Nov 22 at 19:29










  • Have been waiting for over 10 mins.
    – Bab
    Nov 22 at 19:30


















  • So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
    – Bab
    Nov 22 at 18:12












  • @Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
    – Karol Dowbecki
    Nov 22 at 18:13












  • Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:31












  • Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
    – Bab
    Nov 22 at 19:29










  • Have been waiting for over 10 mins.
    – Bab
    Nov 22 at 19:30
















So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12






So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12














@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
– Karol Dowbecki
Nov 22 at 18:13






@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate Set<possibleKey> for just checking presence of possibleKey.
– Karol Dowbecki
Nov 22 at 18:13














Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31






Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31














Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29




Have tried with while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29












Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30




Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30













1














Map.containsValue() must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue() on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.



Consider instead keeping an auxiliary Set of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.






share|improve this answer





















  • By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:32










  • Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
    – Bab
    Nov 22 at 19:33
















1














Map.containsValue() must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue() on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.



Consider instead keeping an auxiliary Set of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.






share|improve this answer





















  • By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:32










  • Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
    – Bab
    Nov 22 at 19:33














1












1








1






Map.containsValue() must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue() on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.



Consider instead keeping an auxiliary Set of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.






share|improve this answer












Map.containsValue() must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue() on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.



Consider instead keeping an auxiliary Set of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 22 at 18:10









John Bollinger

78.2k73974




78.2k73974












  • By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:32










  • Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
    – Bab
    Nov 22 at 19:33


















  • By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
    – Bab
    Nov 22 at 18:32










  • Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
    – Bab
    Nov 22 at 19:33
















By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32




By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32












Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33




Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); } but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436072%2fwhy-does-checking-if-a-hashmap-has-a-certain-value-take-very-long-to-execute-wit%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

Alexandru Averescu

Trompette piccolo