-2

i have this kind of data structure

Map<Integer, Integer> groupMap= new LinkedHashMap<>();

groupMap.put(10, 1);
groupMap.put(11, 0);
groupMap.put(14, 1);
groupMap.put(13, 0);
groupMap.put(12, 0);
groupMap.put(15, 1);

what can be the best way to find the key which has value 1 if i have a present key with one value. Ex:i have key 14, now need to find the key 15 which has value 1

least looping will be helpfull.

my approch:

List<Integer> keys = new ArrayList<>();
keys.putAll(groupMap.keySet());

//getting the index of current key i have
int index = keys.indexOf(14);

if(keys.size() == index) return -1;

for(int i = index+1;i<keys.size();i++){
   if(groupMap.get(i) == 1) return i;
}

i know it isn't a very good approach, but can you please suggest a good one.

rcb13
  • 73
  • 1
  • 7
  • This question would probably be better for this site: http://codereview.stackexchange.com/ – Jure Jan 20 '16 at 08:34
  • 1
    [Here is a similar question](http://stackoverflow.com/questions/1383797/java-hashmap-how-to-get-key-from-value) – Titus Jan 20 '16 at 08:36
  • 1
    @Jure and the reason is? We have clear problem here with example solution, what is wrong for you? – Dominik Jan 20 '16 at 08:36
  • @Dominik Descripion of codereview is: Code Review is a question and answer site for seeking peer review of your code. rcb13 already solved his logical problem, but now he wants to improve hes code. I thought that codereview's purpose is to improve your code. – Jure Jan 20 '16 at 08:40

3 Answers3

1

This completely defeats the purpose of a key-value map. But if it's really what you want, I suppose you could do the following:

public static int getNextKeyByValue(int value, int previousKey) {
    final Map<Integer, Integer> groupMap = new HashMap<>();
    Iterator iterator = groupMap.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>) iterator.next();
        if (entry.getValue() == value && entry.getKey() != previousKey) {
            return entry.getKey();
        }
    }
    return -1;
}
nbokmans
  • 4,743
  • 2
  • 30
  • 52
  • You should also check that the found key is not the already known key. – Titus Jan 20 '16 at 08:40
  • 1
    @Dominik, his post does not state that he doesn't want to loop. He wants minimal looping - this is minimal. Going over the map in any other way is not going to be any better for performance. I could remove the iterator step and just `for` loop over `groupMap.entrySet()`. – nbokmans Jan 20 '16 at 08:44
  • @Titus I forgot about that, thanks for noticing. I have updated my code appropriately. – nbokmans Jan 20 '16 at 08:48
  • Thanx @nbokmans , acording to this approach if i have 1000 items and current key is 800 and next 1 value key is 900 then this loop go from 0 to 900 while previous approach will go from 800 to 900, please corret me if i am wrong – rcb13 Jan 20 '16 at 10:10
0

I have not really clear your question. If you are looking for all the tuples with value equals to 1, you could follow the approach below:

for (Entry<Integer, Integer> entry : groupMap.entrySet()) {
     if (entry.getValue() == 1) {
         System.out.println("The key is: " + entry.getKey().toString());
     }
}
Giovanni Grano
  • 1,499
  • 3
  • 14
  • 28
0

From the topic which @Titus mentioned in the comment, the most elegant and shortest solution is to use stream:

int getFirstCorrectValueBiggerThan (int lastValue) {
    return groupMap.entrySet().stream()
            .filter(entry -> Objects.equals(entry.getValue(), 1))
            .map(Map.Entry::getKey)
            .filter(value -> value > lastValue)
            .findFirst();
}

edit: sorry for the mistake, the code provided does not solve your problem since it is comparing keys not indexes. Here you have proper version, however it is not so cool anymore.

ArrayList<Integer> filteredList = groupMap.entrySet().stream()
     .filter(entry -> entry.getValue().equals(1))
     .map(Map.Entry::getKey)
     .collect(Collectors.toCollection(ArrayList::new));
int nextCorrectElement = filteredList.get(filteredList.indexOf(14) + 1);

update as far as i undestand what is written in this tutorial about map:

When a user calls put(K key, V value) or get(Object key), the function computes the index of the bucket in which the Entry should be. Then, the function iterates through the list to look for the Entry that has the same key (using the equals() function of the key).

and check out this topic about hash map complexity.

O(1) certainly isn't guaranteed - but it's usually what you should assume when considering which algorithms and data structures to use.

On top of that, the key part of your solution- the ArrayList::indexOf- is O(N) complex- you have to iterate through each element till the one which meets the condition. More info is in this topic.

So efectively you are iterating through every element of your hashmap anyway. And what is more, the hashmap searching (get method) is not quaranteed to be O(1) complex so there is a chance that you will double your work.

I have made a simple test of performance for stream based solution and simple loop proposed in this topic. In fact loop will be faster than sequential stream for each case I think, but still if you want that kind of performance gain then try to write it in in C++. Otherwise if you have more complex example then using the parallel stream may get some advantage due to higher abstraction level of the problem stating.

Community
  • 1
  • 1
Dominik
  • 323
  • 1
  • 4
  • 12
  • thanx @Dominik for a better approach, but i think that filtering to the entrySet() map + after that finding the item = total looping through the item (unless filtering gives a 0(1) complexity like hash maps) – rcb13 Jan 20 '16 at 10:16
  • @rcb13 ArrayList::indexOf (which u have used) complexity is O(N) according to http://stackoverflow.com/questions/21388466/is-arraylist-indexof-complexity-n I am updating my answer – Dominik Jan 20 '16 at 11:26
  • am i assuming right that lastValue is a/c to my question is somewhat 14..? – rcb13 Jan 20 '16 at 12:39
  • i am not sure if i understood properly, but lastValue from my code with your example data will be 14. ohh, i think that i have misunderstood the problem little bit. let me modify the solution in a minutes. – Dominik Jan 20 '16 at 12:42
  • thanx, but **.filter(value -> value > lastValue)** will not work, as map not in sorted order and linkedhashMap has been used for ordering, so i badly need index in this case. – rcb13 Jan 20 '16 at 12:45
  • fixed. : ) check out if you like it. Actually I think your own solution is fine. However I am not sure if a hashmap collection is the best choice for your task (which I do not know about at all) since answer to your question require some different functionalities than map interface provides (i.e. indexing). Like @nbokmans pointed out before. – Dominik Jan 20 '16 at 13:39
  • thanx @Dominik for your effort, your answer is suitable, i have been switched to the solution using ValueComparator and TreeMap, but still that's not very good, thanx. – rcb13 Jan 20 '16 at 14:27
  • it was quite fun :) hope you will deal with it somehow. – Dominik Jan 20 '16 at 14:29