-2

I'm trying to iterate through a Linked HashMap keySet however I am having difficulties in getting it to work.

Essentially I am searching the keySet to find a word, and another word. If the second word is immediately after the first word I wish to return true. This is the progress I have made so far.

for (String word : storedWords.keySet()) {

        value0++;

        if(word.equals(firstWord)){
            value1 = value0;
        }

        if(word.equals(secondWord)){
            value2 = value0;
        }

        int value3 = value2 - 1;
        if(value1 == value3){
            result = true;
            break;
        }
    }

EDIT:

I've solved my problem and am thankful for all of those who helped. I apologise for making a post when there was a lot of information available on the website however I just lacked the understanding of the logic behind it.

  • 1
    Does this answer your question? [How do I efficiently iterate over each entry in a Java Map?](https://stackoverflow.com/questions/46898/how-do-i-efficiently-iterate-over-each-entry-in-a-java-map) – SternK Jan 13 '20 at 18:02
  • @SternK It does thank you, I've tried this method and haven't had luck which I why I decided to make a thread as I was struggling to understand it. I will try again using this thread and report back. Thank you for your time. – Dalton Whitestone Jan 13 '20 at 18:04
  • 1
    You already iterate through the map's key set. What is your actual intent here, and what specifically isn't working? – M. Prokhorov Jan 13 '20 at 18:05

3 Answers3

1

You can avoid iterating over the whole keySet by storing the indices of each element in a separate map; then you can just test if both keys are present and have indices differing by 1. For convenience, encapsulate both maps into an object:

import java.util.*;

public class MapWithIndices<K, V> {
    private final Map<K, V> map = new LinkedHashMap<>();
    private final Map<K, Integer> indices = new HashMap<>();

    public V get(K k) {
        return map.get(k);
    }

    public V put(K k, V v) {
        V old = map.put(k, v);
        if(old == null) {
            indices.put(k, indices.size());
        }
        return old;
    }

    public boolean areAdjacent(K k1, K k2) {
        Integer i1 = indices.get(k1);
        Integer i2 = indices.get(k2);
        return i1 != null && i2 != null && i1 + 1 == i2;
    }
}

You can add more Map methods (e.g. size) by delegating them to map. However, the remove method cannot be implemented efficiently since it requires recomputing all later indices. If removing from the map is required, an alternative data structure design should be considered; for example, indices can store the original insertion order of each key, and an order statistic tree can be used to count how many existing keys have a lower original-insertion-order.

kaya3
  • 47,440
  • 4
  • 68
  • 97
  • How about using a (doubly) linked list instead of indexes? That would support removal and be fairly simple. Granted, since LinkedHashMap already uses one, it would be reinventing the wheel and then attaching it to your existing wheel. Sad that LinkedHashMap doesn't offer a method taking a key and returning an iterator that's at that key... – Kelly Bundy Jan 13 '20 at 19:45
  • Yes, you could roll your own linked list and put your linked list nodes into the hashmap, basically implementing your own version of LinkedHashMap with the extra behaviour of being able to tell whether or not two nodes are adjacent. Certainly it is an option, yes. – kaya3 Jan 13 '20 at 19:48
  • Hello @kaya3, thank you for writing a solution for me. I learned a fair bit from your post as well, I now noticed that I created a lot of unneeded variables where as you achieved the same effect by using different logic. Thankfully I don't need to remove anything but I will be sure to take into account that this method wouldn't work if I was to implement that feature. Again thank you for taking the time to provide me with this information. – Dalton Whitestone Jan 13 '20 at 20:08
0
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}
user1850484
  • 388
  • 1
  • 3
  • 23
  • 3
    Code-only answers are not encouraged, please add some context to explain how this answer will solve the problem in question – Jawad Jan 13 '20 at 21:18
  • Your answer only shows how to iterate through the collection. It does not answer the question asked: how to stop if the iterator hits `secondWord` right after `firstWord`. – Daniel Junglas Jan 14 '20 at 08:39
0

I think this is sort of in line with what you started with. You might want to test the performance though.

import java.util.LinkedHashMap;
import java.util.Map;

class Testing {
  Map<String, Integer> storedWords = new LinkedHashMap<>();
  {
    storedWords.put("One",1);
    storedWords.put("Two",2);
    storedWords.put("Three",3);
    storedWords.put("Four",4);
    storedWords.put("Five",5);
  }

  public static void main(String[] args) {
    Testing t = new Testing();
    String firstWord;
    String secondWord;

    firstWord = "Three";
    secondWord = "Five";
    System.out.println(t.consecutive(firstWord, secondWord)); // false

    firstWord = "Two";
    secondWord = "Three";
    System.out.println(t.consecutive(firstWord, secondWord)); // true
  }

  public boolean consecutive(String firstWord, String secondWord) {
    boolean foundfirst = false;  
    for (String word : storedWords.keySet()) {
      if (!foundfirst && word.equals(firstWord)){
        foundfirst = true;
        continue;
      }

      if (foundfirst) {
        if(word.equals(secondWord)){
          return true;
        } else {
          foundfirst = false; // reset to search for the first word again
        }
      }
    }
    return false;
  }
}
Scratte
  • 3,056
  • 6
  • 19
  • 26
  • Hello @Scratte, thank you very much for taking the time to do that. It's really frustrating when you're unable to think of the correct logic on how to code a problem. Appreciate you showing me a solution for this. – Dalton Whitestone Jan 13 '20 at 20:06
  • You're welcome. I thought it was a fun exercise. I had a look at the other solution by kaya3, but I didn't actually try it out. It looks like it will perform a lot better. You'd need to keep two lists though. – Scratte Jan 13 '20 at 20:26