1

I am working on an XML file. In my XML file, there are somes nodes which have childs. This XML file has multiple tags.

<Cat categorie="CAT 1" guid="e9fdsd8ff">
    <!--Electric energie management-->
    **<item Var="VAR1" guid="2795ddsd410d">
        <desc> Energie Smart Management 
        </desc>
        <App guid="240adsqsd" />
        <App guid="90dqddqsq" />**
    </item>
</Cat>

Like you can see, my node "item " has the argument VAR=var1 and has 2 childs. So I created a hashMap to put, for 1 node his childs like below

private Map<String, Collection <String >> multiMap = new HashMap <> ();

So I Have something like that actually : [Key=Var1, Value = [gui0,guid1,...]]

Now, I would like to know if you knew how to verify if a guid is contained in a collection associated with a key in order to retrieve this key.

For example, if I have this String : 240adsqsd. I want to recover Var1.

Thanks for your help

Dici
  • 25,226
  • 7
  • 41
  • 82
  • Welcome to SO, Please add what you have tried so far in terms of reading documentations or code, what problem you are facing. Add exact issue instead of a question with "I need you to solve the following problem". – dkb Dec 14 '18 at 12:33
  • 2
    Well a map is made for accessing a value from a key not a key from a value. You're just misusing your data structure here. – Dici Dec 14 '18 at 12:39
  • It's possible that a string occurs multiple times inside the values of `multiMap` do you want all keys which contain this value? Or the first? The last? – Mark Dec 14 '18 at 12:40
  • Thanks for the update, the question is getting clearer. It's not completely clear to me yet though. What id are you going to query in the map and what is the expected answer? – Dici Dec 14 '18 at 12:55
  • Thanks for the other update. You can check my answer if you want, I had understood your use-case correctly. – Dici Dec 14 '18 at 13:06

4 Answers4

1

It is possible. Say you have the key myKey and you want to know if the string mySearchString is contained in the collection behind that key.

multiMap.get("myKey").contains("mySearchString");

It will return true if mySearchString equals (case sensitive) any object in the colelction.

You have to be careful though, the method contains on a collection uses the case sensitive equals method and will only work when they are 100% equal. So when your collection contains something like "MYSEARCHstring", it won't work, as well as "The sentence that contains mySearchString".

EDIT:
(Thanks Nikolas and Dici)
Here a more complete example how to achieve that.

String mySearchString = "mySearchString";
Map<String, Collection<String>> multiMap = new HashMap<>();
for (String key : multiMap.keySet()) {
    if (multiMap.get(key) != null && multiMap.get(key).contains(mySearchString)) {
        return key;
    }
}

If you don't know the key, you have to iterate over your map, check if one of the collections contains the searched string and then, when you found the collection (and its key) return the key.

GameDroids
  • 5,584
  • 6
  • 40
  • 59
  • It throws the NPE when `get("myKey")` returns `null`. – Nikolas Charalambidis Dec 14 '18 at 12:44
  • It's not how I understood the question. It seemed to me as though the key was unknown and was in fact what the OP is looking for retrieving. I may have misread it. – Dici Dec 14 '18 at 12:50
  • Also, it's wrong to state that any collection uses the `equals` function, for example a `TreeSet` would use the `compare` method. It is also case-sensitive though, so it doesn't change your wider point. – Dici Dec 14 '18 at 12:51
  • PS: your updated answer has linear complexity, which makes the use of a map pointless. A list would have the same complexity. – Dici Dec 14 '18 at 12:52
  • @Dici you are right, this is far from the best, most accurate or most versatile solution (I would never suggest that), but it should serves as a comprehensible example how it can be achieved. And using a `Map` can have multiple advantages, regardless of the complexity of your algorithms. – GameDroids Dec 14 '18 at 13:02
  • @GameDroids I don't know, if I'm answering a data structure question I'm going to suggest the data structure that solves this problem the best. Data structures are mostly invented to make some operations fast, I don't see what other reason to use a highly sophisticated implementation of a map versus a simple linear lookup in a list there could be. – Dici Dec 14 '18 at 13:04
0

A test without map modification would be:

boolean contained = multiMap.getOrDefault(key, Collections.emptyList()).contains(key);

Then there are Map.computeIfAbsent, computeIfPresent, merge if you want to update the map.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

If I understand your question, you actually want to reverse your map because a map is good at accessing a value given a key not at finding a key given a value. Here's some pseudo-code to build the map:

map = new Map()
for item in items
    for app in item.apps
        map.put(app.guid, item.guid) // assuming guids are always unique

That would give you a Map<String, String> rather than Map<String, Collection<String>>. The former is good at telling you which item contains an application, the later is good at telling you which apps a given item contains. Given your reverse mapping map, you will be able to do the following:

// could just have Map<App, Item> appToItem if you build your map differently 
// and App and Item define hashCode and equals
public boolean findVar(String appId, Map<String, String> appToItem, Map<String, Item> itemsById) {
    Item item = itemsById.get(appToItem.get(appId));
    if (item == null) return null;
    return item.getVar();
}
Dici
  • 25,226
  • 7
  • 41
  • 82
  • Thks to help me. Well, for 1 key, I can have many values. I need to recover my key thanks a string. If the String is one of the values ​​among others then I get the key again –  Dec 14 '18 at 13:11
  • Np, does it solve your problem or is something missing? – Dici Dec 14 '18 at 13:13
0

Thank you to everyone for your answers.

If I understand correctly, it is preferable that I look for a value not his key.

So let's admit that I choose this option.

Can I recure each value for a key.

If my key is Var1 for example, would it be better for me to recover all its values?

  • I think you should ask another question or update your question rather than creating an answer that asks a question. – Dici Dec 14 '18 at 13:53
  • And the answer to your question is no, typical maps are uni-directional. If you want to make lookups in both directions you will need two maps. If you want to use a library, Guava abstracts this for you. Check this answer: https://stackoverflow.com/questions/9783020/bidirectional-map – Dici Dec 14 '18 at 13:55