Multi-Dimensional Array(or other structure) in Java - java

I come from PHP, i'm developping a tool, and i need to use a multidimensional array ( or something other, map,..)
My goal is to be able to have an ArrayList like that :
[["name1", "surname1", "age"], ["name1", "surname1", "age"]]
Or :
[["name" : "name1", "surname" : "surname1", "age" : "age1"], ["name" : "name2", "surname" : "surname2", "age" : "age2"]]
And to be able to add another list into this global list, without size limit.
Actually, i do not found that in Java, it's crazy xD.
The goal after that it to filter (with something like in PHP ((multi sort) to be able to sort those arrays which areinside the global array.
( I need to sort a key of those list,in order to get the most recent, and then i save the first list which is the most recent ).
So actually, i only arrive to get an arraylist.. but not multidimensionnal..
Thanks for tips :)
(I use spring boot )
EDIT 1 :
HashMap<String, String> myhash = new HashMap<String, String>();
myhash.put("Cat1", "james");
myhash.put("Cat2", "adams");
myhash.put("Cat3", "turk");
System.out.println(myhash);
// {Cat3=turk, Cat2=adams, Cat1=james}
// I Would like : [{Cat3=turk, Cat2=adams, Cat1=james}, {Cat3=turkother, Cat2=adamsother, Cat1=jamesother}, {Cat3=fred, Cat2=ded, Cat1=tp}]

You mean HashMap<String, ArrayList<String>> and than use filter on the HashMap.keyset().
But don't know if this is exactly what your are looking for.
Two notes:
This is basic Java. No Spring required.
If you make a nice Java object with the properties you are looking for, perhaps filtering will be more easier... But don't know. I would create an object Person with the required properties, store it in an ArraysList and than use this object further.
Update:
HashMap<String, String> myhash = new HashMap<String, String>();
myhash.put("Cat1", "james");
myhash.put("Cat2", "adams");
myhash.put("Cat3", "turk");
System.out.println(myhash);
// {Cat3=turk, Cat2=adams, Cat1=james}
// I Would like : [{Cat3=turk, Cat2=adams, Cat1=james}, {Cat3=turk, Cat2=adams, Cat1=james}]
ArrayList<HashMap<String, String>> lst = new ArrayList<>();
lst.add(myhash);
lst.add(myhash);
System.out.println(lst); //[{Cat3=turk, Cat2=adams, Cat1=james}, {Cat3=turk, Cat2=adams, Cat1=james}]
Remark:
take care that myhash is added twice ==> if you change on the one field ==> changes on the other field is done as well
I don't see much value in this sample. Especially since the Map is added twice.
Take a look at the different samples for streams - for filtering and sorting. This might be useful.
If there are more qs I would guess its better to create a different q. I think that's it ... Feel free to ask ...

Here is how you have a list of lists in Java.
ArrayList<ArrayList<String>> myList = new ArrayList<>();

Related

comparing two objects and finding the missing fields with java

I want to find the the recipes from the users provided ingredients
and tell the user the missing ingredient from the main recipe's ingredients
how can i find the missing ingredients ? i mean how should I query to to comparing ?
{
"ingredients":[
{"title":"apple"},
{"title":"cheese"},
{"title":"banana"},
{"title":"orange"},
]
}
The second would be :
[
{"title":"apple"},
{"title":"cheese"},
]
It should give us the missing two others like :
{"title":"banana"},
{"title":"orange"},
I'm not sure what objects you intend to use, but if each object possessed a Set of these values, you could find the difference as per Prabhaker A's answer here like so:
Set<String> objectASet = new HashSet<>(Arrays.asList("apple", "cheese", "banana", "orange"));
Set<String> objectBSet = new HashSet<>(Arrays.asList("apple", "cheese"));
Set<String> differenceSet = objectASet.removall(objectBSet);
This will change the values of object A's set, however, so a copy will need to be made to preserve those values.

Map inside a Map with Jackson with JSF

I'm using Jackson to read/write datas from/into json files and I have an issue with the User POJO. It has a Map wich is supposed to be the ways to contact the User (so it can have from 0 to 7, depending on the Enum). I want to be able to put ways to contact using a form in JSF.
I tried something like value="#{config.user.contacts[EMAIL_PRO]}"
where of course EMAIL_PRO is an Enum (later, the user should be able to chose the Enum himself, but right now I try simple).
But when I do so, the error is
Null key for a Map not allowed in JSON
wich I understand, 'cause my debug says that the value returned is{null = null}. Now first question : since the map is empty, is JSF supposed to work simply like that ? The key "EMAIL_PRO" doesnt exists yet, but shouldn't JSF make the work done for me, and put right value with the key ?
The other question is much more about Jackson and Maps. As I said, my POJO User contains a Map, and the json file is a Map himself (containing multiple users).
Is it really possible to write a Map into this file using Jackson where the Map is Map<String, Object> and the Object contains a Map<Enum, Object> ? And if yes, how ?
Thanks for the help
PS: I cannot change either my APIs or my POJOs.
I think this is a repeated post, see How to convert hashmap to JSON object in Java
And as it says on one of the responses:
Map<String, Object> data = new HashMap<String, Object>();
data.put( "name", "Mars" );
data.put( "age", 32 );
data.put( "city", "NY" );
JSONObject json = new JSONObject();
json.putAll( data );
System.out.printf( "JSON: %s", json.toString(2) );
output:
JSON: {
"age": 32,
"name": "Mars",
"city": "NY"
}
You can also try to use Google's GSON.Google's GSON is the best library available to convert Java Objects into their JSON representation

HashMap: Find next lower key

I am currently storing marshalling libraries for different client versions in a HashMap.
The libs are loaded using the org.reflections API. For simplicity sake I'll just insert a few values here by hand. They are unordered by intent, because I have no influence on in which order the map is initialized on start-up by the reflections API.
The keys (ClientVersion) are enums.
HashMap<ClientVersion, IMarshalLib> MAP = new HashMap<>();
MAP.put(ClientVersion.V100, new MarshalLib100());
MAP.put(ClientVersion.V110, new MarshalLib110());
MAP.put(ClientVersion.V102, new MarshalLib102());
MAP.put(ClientVersion.V101, new MarshalLib101());
MAP.put(ClientVersion.V150, new MarshalLib150());
All and well so far, the problem now is, that there are client versions out there where the marshalling did not change since the previous version.
Let's say, we have a client version ClientVersion.V140. In this particular case I am looking for MarshalLib110, assigned to ClientVersion.V110.
How would I get the desired result (without iterating through all entries and grabbing "the next lower" value each time)?
Thanks in advance!
How would I get the desired result (without iterating through all entries and grabbing "the next lower" value each time)
There is nothing you can do about "iterating through all entries" part: since the map is unordered, there is no way of finding the next smaller item without iterating the entire set of keys.
However, there is something you can do about the "each time" part: if you make a copy of this map into a TreeMap, you would be able to look up the next smaller item by calling the floorEntry method.
Another alternative is to copy the keys into an array on the side, sort the array, and run a binary search each time that you need to look up the next smaller key. With the key in hand, you can look up the entry in your hash map.
I recommend you to use NavigableSet. Look at this example:
HashMap<Integer, String> map = new HashMap<>();
map.put(100, "MarshalLib100");
map.put(110, "MarshalLib110");
map.put(102, "MarshalLib102");
map.put(101, "MarshalLib101");
map.put(150, "MarshalLib150");
NavigableSet<Integer> set = new TreeSet<>(map.keySet());
Integer key = set.lower(150); // ^ -> 110
String val = map.get(key); // ^ -> MarshalLib110
// or
key = set.higher(110);// ^ -> 150
val = map.get(key); // ^ -> MarshalLib150
Update: Using TreeMap to find next lower key is not really correct. Example:
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
treeMap.put(100, "MarshalLib100");
treeMap.put(110, "MarshalLib110");
treeMap.put(102, "MarshalLib102");
treeMap.put(101, "MarshalLib101");
treeMap.put(150, "MarshalLib150");
System.out.println(treeMap.floorKey(102));
System.out.println(treeMap.floorEntry(102));
System.out.println(treeMap.ceilingKey(102));
System.out.println(treeMap.ceilingEntry(102));
Output:
102
102=MarshalLib102
102
102=MarshalLib102

ADOBE CQ5 JCR - How to orderby/sorting query builder result using node's property

basically below is the java coding part, which the result will then be populated to a .csv file. However, I dont seem get the ordering part right (last line in below snippet).
Map<String, String> map = new HashMap<String, String>();
map.put("path", "/etc/crx-db/form-data/career");
map.put("type", "nt:unstructured");
map.put("p.limit", "-1");
map.put("daterange.property", "created");
map.put("daterange.lowerBound", from);
map.put("daterange.lowerOperation", ">=");
map.put("daterange.upperOperation", "<=");
map.put("daterange.upperBound", to);
map.put("orderby", "created"); //<--here
Providing that in crx repositry (/etc/crx-db/form-data/career), I have nodes: data1, data2, data3...
Then for each node, there is one property - Name: created | Type: Date | Value: 2014-01-28T23:21:15.029+08:00 (eg)
However my result in .csv is incorrect like (row 1 to 5):
2014-01-28T23:21:15.029+08:00
2014-01-28T23:48:12.219+08:00
2014-02-10T18:44:38.914+08:00 <-- unsorted
2014-02-10T18:43:32.426+08:00 <-- unsorted
2014-02-10T18:46:53.319+08:00
Pretty sure my code wasn't running. Any idea on how can I tweak my java code to make the sorting happen? As in returning sorted data1, data2, data3... based on the property created. Thanks.
You were almost there. It can be done as follows.
map.put("orderby", "#created");
map.put("orderby.sort", "desc"); // in case you want it descending
In case you need to check property within a child node, you can provide the relative path to that for the orderby value. For eg., if you are searching for dam:Asset and want to order them based on the jcr:lastModified property of its metadata, then your query would be something similar to this.
map.put("path", "/content/dam/geometrixx");
map.put("type", "dam:Asset");
map.put("orderby","#jcr:content/metadata/jcr:lastModified");
For further learning refer this

ElasticSearch Java API to query and return single column instead of the whole json document

While searching using java api in elaticsearch, I would like to retrieve only one column.
Currently when I query using the Java API it returns the whole record like this: [{_id=123-456-7890, name=Wonder Woman, gender=FEMALE}, {_id=777-990-7890, name=Cat Woman, gender=FEMALE}]
The record above correctly matches the search condition shown in th . As shown in the code below:
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
SearchRequestBuilder srb = client.prepareSearch("heros")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
MatchQueryBuilder mqb;
mqb = QueryBuilders.matchQuery("name", "Woman");
srb.setQuery(mqb);
SearchResponse response = srb.execute().actionGet();
long totalHitCount = response.getHits().getTotalHits();
System.out.println(response.getHits().getTotalHits());
for (SearchHit hit : response.getHits()) {
result.add(hit.getSource());
}
System.out.println(result);
I want only one column to be returned. If I search for name I just want the full names back in a list: "Wonder Woman", "Cat Woman" only not the whole json record for each of them. If you think I need to iterate over the result list of maps in java please propose an example of how to do that in this case.
You can specify the fields to be returned from a search, per documentation. This can be set via SearchRequestBuilder.addFields(String... fields), ie:
SearchRequestBuilder srb = client.prepareSearch("heros")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.addFields("name");
Better combine both:
use .addFields("name") to tell ES that it needs to return only this
column
use hit.field("name").getValue().toString() to get the result
It is important to use .addFields when you don't need the whole document, but the specific field/s as it will lower the overhead and the network traffic
I figured it out.
List<String> valuesList= new ArrayList<String>();
for (SearchHit hit : response.getHits()) {
result.add(hit.getSource());
valuesList.add(hit.getSource().get("name").toString());
}
The other solutions didn't work for me, hit.getSource() was returning null. Maybe they are deprecated? Not sure. But here was my solution, which FYI can speed things up considerably if you are only getting one field and you are getting lots of results.
Use addFields(Strings) on your SearchRequestBuilder as mentioned, but then when you are getting the values you need to use:
hit.getFields().get( fieldName ).getValue()
or
hit.getFields().get( fieldName ).getValues()
to get a single value or a list of values depending on the field.

Categories