Check value inside Map - java

I have a Map where I save values with the form NAME-GROUP.
Before doing some operations, I need to know if the Map contains a specific group,
for example: I need to check for values containing group1 like Mark-group1.
I'm trying to get it this way:
if (checkList.containsValue(group1)) {
exists = true;
}
I can't provide the name when searching because there could be diferent names with the same group.
But it isn't finding the value, as seems that this function just looks for the entire value string and not only for part of it.
So, there would be any way of achieving this, or would I need to change the way I'm focusing my code.
Update--
This is the looking of my Map:
Map<Integer, String> checkList = new HashMap<Integer, String>();
I load some values from a database and I set them into the Map:
if (c.moveToFirst()) {
int checkKey = 0;
do {
checkKey++;
checkList.put(checkKey, c.getString(c.getColumnIndex(TravelOrder.RELATION)));
}while(c.moveToNext());
}
The relation column, has values like: mark-group1, jerry-group1, lewis-group2, etc...
So, the Map will have a structure like [1, mark-group1], etc...
What I need is to check if there is any value inside the map that contains the string group1 for example, I don't care about the name, I just need to know if that group exists there.

If you want to check any value contain your string as a substring you have to do the following:
for (String value : yourMap.values()) {
if (value.contains(subString)) {
return true;
}
}
return false;
By the way if your values in the map are really have two different parts, i suggest to store them in a structure with two fields, so they can be easily searched.

Related

How to add specific "key" to an ASN1EncodableVector in BouncyCastle?

So, I asked a similar question before but the issue has since evolved. So, I'll give you a whole overview and then I'll ask the question.
Currently, I am reading from a .yml file and parsing through it. I then store the data in a HashMap<String, ArrayList > that looks something like this:
[{p_table=[p_event/Name, p_fault/Name]},
{s_table=[s_event/Name, s_fault/Name]},
{r_table=[r_event/Name, r_fault/Name]}]
Now, I understand that if I want to create an extension with bouncycastle I first have to add all of my data into an ASN1EncodableVector. What I'm doing is using certificates to tell my IoT things what topics they can subscribe/publish/receive from. Hence, I can do something like this:
while(iterator.hasNext()) {
Entry<String, ArrayList<String>> entry = iterator.next();
ASN1EncodableVector vector = new ASN1EncodableVector
for(String val : entry.getValue()) {
(vector).add(new DERUTF8String(val));
}
allowedTables.add(new DERSequence(vector));
}
This will only add the values from the arraylist eg p_event/Name or p_fault/Name, is there a way for me to specify that those two DERUTF8String(s) belong to the p_table? Or is there some sort of identifier I can use when using the .add method?
So could the code change from something like this:
(vector).add(new DERUTF8String(val));
to:
(vector).add(new aConstructorToIdentifyWhatTheUTF8BelongsTo(entry.getKey()), new DERUTF8String(val));
You can nest sequences, i.e. you can build one DERSequence for each entry as you are doing and then add each of them to an outer ASN1EncodableVector and make a final sequence from that. The inner sequences could contain key/val/val if the number of values is fixed at 2 as in your example. Or you could have yet another sequence to hold the values e.g.:
SEQUENCE {
SEQUENCE {
"p_table",
SEQUENCE {
"p_event/Name",
"p_fault/Name",
}
},
SEQUENCE {
"s_table",
SEQUENCE {
"s_event/Name",
"s_fault/Name",
"s_other/Name",
}
},
// and so on
}

Compare data of two or more maps

I am stuck with the below requirement and not sure how can I proceed with it:
I have a function like:
public void compareExcel(Map<Object,List<HashMap>>) compareMaps){}
This function will take a map as an input parameter. This map will contain the sheet name vs Sheet values(Column name - column values) mapping.
Basically the function input parameters will be like:
<Excel1,(scenario:10)
(timing: 20)
Excel2,(scenario:30)
(timing: 40)
Excel3,(scenario:50)
(timing: 60)
>
Here my excel1 having two columns(scenario and timings) and having values as 10 and 20 respectively.
In the result, I will be needing the comparison like:
Map>
<scenario, <excel1,10>
<excel2,30>
<excel3,50>
timing, <excel1,20>
<excel2,40>
<excel3,60>
>
Any help will be appreciated.
Create/initialize the details of you output data-structure
LOOP (over the excelName:List pairs in you input)
LOOP (over the List that is the value in the pair)
//Each entry in the list is a map
Get the key-name (e.g. "scenario")
Get the value (e.g. "10")
//You already know the out key (i.e the excelName)
With the three known values, build/add to your output data-structure
On mobile so I can't even check syntax, but...
Map recopilation = new HashMap();
for(Object sheetName : compareMaps.keySet()) {
Map sheet = compareMaps.get(sheetName);
for (Object columnName : sheet.keySet()) {
if (recopilation.get(columnName) == null) {
recopilation.put(columnName, new HashMap());
}
((Map) recopilation.get(columnName)).put(sheetName, sheet.get(columnName));
}
}
Something like that. If it works, you should really throw some generics in there, I didn't mostly to save some typing.

How to store multiple objects from a hashmap that has the same key?

EDIT
I've tried this HashMap with multiple values under the same key, and my hashMap now looks like this HashMap<String, List<Place>> placeMap = new HashMap<>();
Also tried to put Object instead of Place(place is my superclass). But when I now create my subclasses and wants to add them to the HashMap I get:
The method put(String, List) in the type HashMap<String,List<Place>> is not applicable for the arguments (String, NamedPlace)
and
The method put(String, List) in the type HashMap<String,List<Place>> is not applicable for the arguments (String, DescPlace)
here is my adding which created the error:
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
placeMap.put(answer, p);
DescPlace dp = new DescPlace(x,y,answer, desc, col, cat);
mp.add(dp);
placeMap.put(answer, dp);
NamedPlace and DescPlace are both subclasses to Place, and I want them both in the same HashMap..
OP
I'm working on a little project here. The thing is that I need to use a HashMap instead of a ArrayList on this part of the project because HashMap is alot faster for searching. I've created a HashMap like this:
HashMap<String, Object> placeMap = new HashMap<>();
The String is the name of the Object, but the thing is that more than one object can have the same name. So I search for a object in my searchfield and I want to store all those objects that has that name into an ArrayList so I can change info in just them.
The object have alot of different values, like name, position, some booleans etc.
Do I need to create a HashCode method into my object class which shall create a unique hashcode?
When using a standard Map<String, List<YourClassHere>> instance, it is important to remember that the map's values for each entry will be a List<YourClassHere>, and will not handle it in any special way. So in your case, if you have
private Map<String, List<Place>> placeMap = new HashMap<>();
Then to store values you will need to do as follows:
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
List<Place> list = placeMap.get (answer);
list.add(p);
However, this piece of code has some underlying problems.
It doesn't take into account that answer might not be present in placeMap.
It assumes that there's always a List<Place> instance for each key you query.
So the best way to fix those potential problems is to do as follows (Java 7 and later):
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
if (placeMap.containsKey (answer) && placeMap.get (answer) != null) {
placeMap.get (answer).add(p);
} else {
List<Place> list = new ArrayList<Place> (); // ..or whatever List implementation you need
list.add (p);
placeMap.put (answer, list);
}
If you want to scna through the list of places, the code would look like this:
if (placeMap.containsKey (key) && placeMap.get (answer) != null) {
for (Place p: placeMap.get (key)) {
// Do stuff
}
}

Changing LinkedHashMapValues

Below is data from 2 linkedHashMaps:
valueMap: { y=9.0, c=2.0, m=3.0, x=2.0}
formulaMap: { y=null, ==null, m=null, *=null, x=null, +=null, c=null, -=null, (=null, )=null, /=null}
What I want to do is input the the values from the first map into the corresponding positions in the second map. Both maps take String,Double as parameters.
Here is my attempt so far:
for(Map.Entry<String,Double> entryNumber: valueMap.entrySet()){
double doubleOfValueMap = entryNumber.getValue();
for(String StringFromValueMap: strArray){
for(Map.Entry<String,Double> entryFormula: formulaMap.entrySet()){
String StringFromFormulaMap = entryFormula.toString();
if(StringFromFormulaMap.contains(StringFromValueMap)){
entryFormula.setValue(doubleOfValueMap);
}
}
}
}
The problem with doing this is that it will set all of the values i.e. y,m,x,c to the value of the last double. Iterating through the values won't work either as the values are normally in a different order those in the formulaMap. Ideally what I need is to say is if the string in formulaMap is the same as the string in valueMap, set the value in formulaMap to the same value as in valueMap.
Let me know if you have any ideas as to what I can do?
This is quite simple:
formulaMap.putAll(valueMap);
If your value map contains key which are not contained in formulaMap, and you don't want to alter the original, do:
final Map<String, Double> map = new LinkedHashMap<String, Double>(valueMap);
map.keySet().retainAll(formulaMap.keySet());
formulaMap.putAll(map);
Edit due to comment It appears the problem was not at all what I thought, so here goes:
// The result map
for (final String key: formulaMap.keySet()) {
map.put(formulaMap.get(key), valueMap.get(key));
// Either return the new map, or do:
valueMap.clear();
valueMap.putAll(map);
for(Map.Entry<String,Double> valueFormula: valueMap.entrySet()){
formulaMap.put(valueFormula.getKey(), valueFormula.value());
}

how to manipulate list in java

Edit: My list is sorted as it is coming from a DB
I have an ArrayList that has objects of class People. People has two properties: ssn and terminationReason. So my list looks like this
ArrayList:
ssn TerminatinoReason
123456789 Reason1
123456789 Reason2
123456789 Reason3
568956899 Reason2
000000001 Reason3
000000001 Reason2
I want to change this list up so that there are no duplicates and termination reasons are seperated by commas.
so above list would become
New ArrayList:
ssn TerminatinoReason
123456789 Reason1, Reason2, Reason3
568956899 Reason2
000000001 Reason3, Reason2
I have something going where I am looping through the original list and matching ssn's but it does not seem to work.
Can someone help?
Code I was using was:
String ssn = "";
Iterator it = results.iterator();
ArrayList newList = new ArrayList();
People ob;
while (it.hasNext())
{
ob = (People) it.next();
if (ssn.equalsIgnoreCase(""))
{
newList.add(ob);
ssn = ob.getSSN();
}
else if (ssn.equalsIgnoreCase(ob.getSSN()))
{
//should I get last object from new list and append this termination reason?
ob.getTerminationReason()
}
}
To me, this seems like a good case to use a Multimap, which would allow storing multiple values for a single key.
The Google Collections has a Multimap implementation.
This may mean that the Person object's ssn and terminationReason fields may have to be taken out to be a key and value, respectively. (And those fields will be assumed to be String.)
Basically, it can be used as follows:
Multimap<String, String> m = HashMultimap.create();
// In reality, the following would probably be iterating over the
// Person objects returned from the database, and calling the
// getSSN and getTerminationReasons methods.
m.put("0000001", "Reason1");
m.put("0000001", "Reason2");
m.put("0000001", "Reason3");
m.put("0000002", "Reason1");
m.put("0000002", "Reason2");
m.put("0000002", "Reason3");
for (String ssn : m.keySet())
{
// For each SSN, the termination reasons can be retrieved.
Collection<String> termReasonsList = m.get(ssn);
// Do something with the list of reasons.
}
If necessary, a comma-separated list of a Collection can be produced:
StringBuilder sb = new StringBuilder();
for (String reason : termReasonsList)
{
sb.append(reason);
sb.append(", ");
}
sb.delete(sb.length() - 2, sb.length());
String commaSepList = sb.toString();
This could once again be set to the terminationReason field.
An alternative, as Jonik mentioned in the comments, is to use the StringUtils.join method from Apache Commons Lang could be used to create a comma-separated list.
It should also be noted that the Multimap doesn't specify whether an implementation should or should not allow duplicate key/value pairs, so one should look at which type of Multimap to use.
In this example, the HashMultimap is a good choice, as it does not allow duplicate key/value pairs. This would automatically eliminate any duplicate reasons given for one specific person.
What you might need is a Hash. HashMap maybe usable.
Override equals() and hashCode() inside your People Class.
Make hashCode return the people (person) SSN. This way you will have all People objects with the same SSN in the same "bucket".
Keep in mind that the Map interface implementation classes use key/value pairs for holding your objects so you will have something like myHashMap.add("ssn",peopleobject);
List<People> newlst = new ArrayList<People>();
People last = null;
for (People p : listFromDB) {
if (last == null || !last.ssn.equals(p.ssn)) {
last = new People();
last.ssn = p.ssn;
last.terminationReason = "";
newlst.add(last);
}
if (last.terminationReason.length() > 0) {
last.terminationReason += ", ";
}
last.terminationReason += p.terminationReason;
}
And you get the aggregated list in newlst.
Update: If you are using MySQL, you can use the GROUP_CONCAT function to extract data in your required format. I don't know whether other DB engines have similar function or not.
Update 2: Removed the unnecessary sorting.
Two possible problems:
This won't work if your list isn't sorted
You aren't doing anything with ob.getTerminationReason(). I think you mean to add it to the previous object.
EDIT: Now that i see you´ve edited your question.
As your list is sorted, (by ssn I presume)
Integer currentSSN = null;
List<People> peoplelist = getSortedList();//gets sorted list from DB.
/*Uses foreach construct instead of iterators*/
for (People person:peopleList){
if (currentSSN != null && people.getSSN().equals(currentSSN)){
//same person
system.out.print(person.getReason()+" ");//writes termination reason
}
else{//person has changed. New row.
currentSSN = person.getSSN();
system.out.println(" ");//new row.
system.out.print(person.getSSN()+ " ");//writes row header.
}
}
If you don´t want to display the contents of your list, you could use it to create a MAP and then use it as shown below.
If your list is not sorted
Maybe you should try a different approach, using a Map. Here, ssn would be the key of the map, and values could be a list of People
Map<Integer,List<People>> mymap = getMap();//loads a Map from input data.
for(Integer ssn:mymap.keyset()){
dorow(ssn,mymap.get(ssn));
}
public void dorow(Integer ssn, List<People> reasons){
system.out.print(ssn+" ");
for (People people:reasons){
system.out.print(people.getTerminationReason()+" ");
}
system.out.println("-----");//row separator.
Last but not least, you should override your hashCode() and equals() method on People class.
for example
public void int hashcode(){
return 3*this.reason.hascode();
}

Categories

Resources