How to convert object to map? - java

I need to convert an object i got from database to a map, how can i do that?
Variable that should contain data inside the object
public Map<Byte, Byte> currentSkills = new ConcurrentHashMap<>();
How I get that object from the database
MongoCollection<Document> users = Database.connection.getDatabase("app").getCollection("users");
Document playerInfo = users.find(eq("Name", username)).first();
player.skills.currentSkills = playerInfo.get("Skills");
I made a little research and found some libraries that can do it, is there any way i can do this without using external libraries?

Related

How do i convert Array

I am trying to serialize Observable Maps with an Serialiazation Proxy.
These two properties need to be saved.
private final MapProperty<Integer, Cargo> allCargoStoredMap;
private final MapProperty<Cargo, CargoLogisticData> cargoLogisticDataMap;
I thought i can save the values in an array like this:
this.cargoLogisticDataAsArray = warehouseManagement.getCargoCargoLogisticDataMap().values().toArray(new CargoLogisticData[0]);
this.cargoAsArray = warehouseManagement.getAllCargoStoredMapProperty().values().toArray(new Cargo[0]);
Then i want to pass i to an Constructor, and rebuild the properties.
public Constructor (List<Cargor> cargos, List<CargoLogisticData>) {
ObservableMap<Integer, Cargo> cargos = FXCollections.observableHashMap();
//How do i add my cargos to a map?
this.allCargoStoredMap = new SimpleMapProperty<>(cargos);
}
Any Idea how i can add the the List Entrys to my map?
I thought i maybe have to save 4 Arrays. Two with key, two with values. And then add those again.
Any Ideas ?
This can be a simple solution if I don't get it wrong
allCargoStoredMap.values().stream().forEach(cargo -> {
CargoLogisticData logisticsData=cargoLogisticDataMap.get(cargo);
/*
You have cargo and related logistics data here.
You can create which data model you want to store and use it
*/
})

How to store dictionaries(map) in flatbuffer in Java

I was learning flatbuffers from this link , there was no example to demonstrate how to store dictionary(map). There was a mention of "Storing dictionaries in java/Csharp" in this link , but i did not understand much about it. I am from java background. Any example of how to store dictionary/map in flatbuffers in java would be helpful
I realize this is an old question but I came across it when I was trying to figure out the same thing. Here is what I did to get a "dictionary/map"
Schema File
namespace com.dictionary;
table DataItem{
keyValue:string(key);
name:string;
age:int;
codes[string];
}
table DictionaryRoot{
items:[DataItem];
}
root_type DictionaryRoot;
When you run this through the FlatBuffers compiler flatc -j schema.fbs it will produce two Java files, one named DictionaryRoot.java, the other named DataItem.java.
In your Java application
Using those two generated Java files you will need to construct the buffer. This has to be done from the innermost data to the outermost. So you need to construct your DataItems (and keep track of their offsets) before your DictionaryRoot.
In this example, let's assume that you have a map of Objects in Java that you need to create the buffer from.
List<Integer> offsets = new ArrayList<>();
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
for (Entry<String, DataObj> entry : map.entrySet()) {
DataObj dataObj = entry.getValue();
// use the builder to create the data and keep track of their offsets
int keyValueOffset = builder.createString(entry.getKey());
int nameOffset = builder.createString(dataObj.getName());
int ageOffset = dataObj.getAge();
int[] codesOffsets = dataObj.getCodes().stream().mapToInt(builder::createString)
.toArray();
// use the builder to create a vector using the offsets from above
int codesVectorOffset = DataItem.createCodesVector(builder, codesOffsets);
// now with all the inner data offsets, create the DataItem
DataItem.startDataItem(builder);
DataItem.addKeyValue(builder, keyValueOffset);
DataItem.addName(builder, nameOffset);
DataItem.addAge(builder, ageOffset);
DataItem.addCodes(builder, codesVectorOffset);
// ensure you 'end' the DataItem to get the offset
int dataItemOffset = DataItem.endDataItem(builder);
// track the offsets
offsets.add(dataItemOffset);
}
// use the builder to create a sorted vector from your offsets. This is critical
int sortedVectorOffset = builder.createSortedVectorOfTables(new DataItem(),
offsets.stream().mapToInt(Integer::intValue).toArray());
// now with your sorted vector, create the DictionaryRoot
DictionaryRoot.startDictionaryRoot(builder);
DictionaryRoot.addItems(builder, sortedVectorOffset);
int dictRootOffset = DictionaryRoot.endDictionaryRoot(builder);
// signal to the builder you are done
builder.finish(dictRootOffset);
// Write data to file
FileOutputStream outputStream = new FileOutputStream("output.bin");
outputStream.write(builder.sizedByteArray());
outputStream.close();
I hope that will help someone else along their journey using FlatBuffers.

Convert list to hashmap

Title of the question may give you the impression that it is duplicate question, but according to me it is not.
I am just a few months old in Java and a month old in MongoDB, SpringBoot and REST.
I have a Mongo Collection with 3 fields in a document, _id (default field), appName and appKey. I am using list to iterate through all the documents and find one document whose appName and appKey matches with the one that is passed. This collection right now has only 4 entries, and thus it is running smoothly. But I was reading a bit about collections and found that if there will be a higher number of documents in a collection then the result with list will be much slower than hashMap.
But as I have already said that I am quite new to Java, I am having a bit of trouble converting my code to hashMap, so I was hoping if someone can guide me through this.
I am also attaching my code for reference.
public List<Document> fetchData() {
// Collection that stores appName and appKey
MongoCollection<Document> collection = db.getCollection("info");
List<Document> nameAndKeyList = new ArrayList<Document>();
// Getting the list of appName and appKey from info DB
AggregateIterable<Document> output = collection
.aggregate(Arrays.asList(new BasicDBObject("$group", new BasicDBObject("_id",
new BasicDBObject("_id", "$id").append("appName", "$appName").append("appKey", "$appKey"))
)));
for (Document doc : output) {
nameAndKeyList.add((Document) doc.get("_id"));
}
return nameAndKeyList;
}// End of Method
And then I am calling it in another method of the same class:
List<Document> nameAndKeyList = new ArrayList<>();
//InfoController is the name of the class
InfoController obj1 = new InfoController();
nameAndKeyList = obj1.fetchData();
// Fetching and checking if the appName & appKey pair
// is present in the DB one by one.
// If appName & appKey mismatches, it increments the value
// of 'i' and check them with the other values in DB
for (int i = 0; i < nameAndKeyList.size(); i++) {
"followed by my code"
And if I am not wrong then there will be no need for the above loop also.
Thanks in advance.
You just need a simple find query to get the record you need directly from Mongo DB.
Document document = collection
.find(new Document("appName", someappname).append("appKey", someappkey)).first();
First of all a list is not much slower or faster than an HashMap. A Hasmap is commonly used to save key-pair values such as "ID", "Name" or something like that. In your case I see you are using ArrayList without a specified size for the list. better use a linked list when you do not know the size because an arraylist is holding a array behind and extending this by copying. If you want to generate a Hasmap out of the List or use a Hasmap you need to map an ID and the value to the records.
HashMap<String /*type of the identifier*/, String /*type of value*/> map = new HashMap<String,String>();
for (Document doc : output) {
map.put(doc.get("_id"), doc.get("_value"));
}
First, avoid premature optimization (lookup the expression if you don’t know what it is). Put a realistic number of thousands of items containing near-realistic data in your list. Try to retrieve an item that isn’t there. This will force your for loop to traverse the entire list. See how long it takes. Try a number of times to get an impression of whether you get impatient. If you don’t, you’re done.
If you find out that you need a speed-up, I agree that HashMap is one of the obvious solutions to try. One of the first things to consider with this is a key type for you HashMap. As I understand, what you need to search for is an item where appName and appKey are both right. The good solution is to write a simple class with these two fields and equals and hashCode methods (I’ll call it DocumentHashMapKey for now, think of a better name). For hashCode(), try Objects.hash(appName, appKey). If it doesn’t give satisfactory performance with the data you have, consider alternatives. Now you are ready to build your HashMap< DocumentHashMapKey, Document>.
If you’re lazy or just want a first impression of how a HashMap performs, you may also build your keys by concatenating appName + "$##" + appKey (where the string in the middle is something that is unlikely to be part of a name or key) and use HashMap<String, Document>.
Everything I said can be refined depending on your needs. This was just to get you started.
Thanks everyone for your help, without which I would not have got to a solution.
public HashMap<String, String> fetchData() {
// Collection that stores appName and apiKey
MongoCollection<Document> collection = db.getCollection("info");
HashMap<String, String> appKeys = new HashMap<String, String>();
// Getting the list of appName and appKey from info DB
AggregateIterable<Document> output = collection
.aggregate(Arrays.asList(new BasicDBObject("$group", new BasicDBObject("_id",
new BasicDBObject("_id", "$id").append("appName", "$appName").append("appKey", "$appKey"))
)));
String appName = null;
String appKey = null;
for (Document doc : output) {
Document temp = (Document) doc.get("_id");
appName = (String) temp.get("appName");
appKey = (String) temp.get("appKey");
appKeys.put(appName, appKey);
}
return appKeys;
Calling the above method into another method of the same class.
InfoController obj = new InfoController();
//Fetching the values of 'appName' & 'appKey' sent from 'info' DB
HashMap<String, String> appKeys = obj.fetchData();
storedAppkey = appKeys.get(appName);
//Handling the case of mismatch
if (storedAppkey == null || storedApikey.compareTo(appKey)!=0)
{//Then the response and further processing that I need to do.
Now what HashMap has done is that it has made my code more readable and the 'for' loop that I was using for iterating is gone, although it might not make much difference in the performance as of now.
Thanks once again to everyone for your help and support.

Update existing entry within a map attribute using DynamoDBMapper

I'm using DynamoDBMapper from the AWS Java SDK and working with a fairly simple item: it has a string attribute (used as the hash key) and a map attribute.
#DynamoDBTable(tableName = "MyTable")
public class MyItem {
private String myStringAttr;
private Map<String, String> myMapAttr;
#DynamoDBHashKey(attributeName = "MyStringAttribute")
public String getMyKeyAttr() { return myKeyAttr; }
public void setMyKeyAttr(String myKeyAttr) { this.myKeyAttr = myKeyAttr; }
#DynamoDBAttribute(attributeName = "MyMapAttribute")
public Map<String, String> getMyMapAttr() { return myMapAttr; }
public void setMyMapAttr(Map<string, string> myMapAttr) { this.myMapAttr = myMapAttr; }
}
I can read and write my object using the load() and save() methods just fine. The issue I'm running into is when I need to update or add a single entry in the map for an existing item in the table. Without knowing the existing entries of the map for said item (and I don't want to perform a load() each time before I attempt to update or add), the best I seem to be able to do is wipe out the entire map and replace it with the single entry I'm trying to update or add. Is it possible to add/update a single entry to an existing item's map attribute using the DynamoDBMapper?
I've looked at the various options provided by DynamoDBSaveExpression and DynamoDBMapperConfig. The closest option I can find is DynamoDBMapperConfig.SaveBehavior.APPEND_SET, but this is for set type attributes rather than the map type I'm using.
I'm able to achieve this exact use case using the Document API's updateItem() method along with an UpdateItemSpec containing an UpdateExpression as shown below. This will add a new entry to the map if the given key doesn't yet exist, or update the value to the one specific if an existing entry does exist, all without touching the other entries in the map. However, I have found the Document API rather cumbersome to work with and would prefer to stick with the DynamoDBMapper if at all possible.
Table table = dynamoDB.getTable("MyTable");
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey("MyStringAttribute", 1)
.withUpdateExpression("set #mma.#mek = :mev")
.withNameMap(new NameMap()
.with("#mma", "MyMapAttribute")
.with("#mek", "SomeMapEntryKey")
.withValueMap(new ValueMap()
.withString(":mev", "Some map entry value"));
UpdateItemOutcome outcome = table.updateItem(updateItemSpec);
One possible solution would be:-
1) Get the data from the table "MyTable" using DynamoDBMapper load
2) Add new entries to the map in the object retrieved in step 1 and save that object using DynamoDBMapper with config as mentioned below
DynamoDBMapperConfig dynamoDBMapperConfig = new DynamoDBMapperConfig(SaveBehavior.UPDATE);
I know that this is a two step process. However, when I was in the same situation, I have tried a lot and couldn't find any solution with single direct update for "Map" data type using DynamoDBMapper.
Hope this helps!

Using one variable as an another variable of different data type but the same name

I am using a class where I am taking input as the file name and the file location. I have a pre defined file names, so I will match the predefined file names with the file name that I received and then store the values accordingly. Please look at the code below
//Set of storage maps and tables
public class storage
{
//Storage set
public static Set<Integer> tiger = new HashSet<Integer>();
//Storage set
public static Set<Integer> lion = new HashSet<Integer>();
//This is the table used for storing the browser customer count
public static Table<String,String,Integer> elephant = HashBasedTable.create();
//Storage map
public static Map<String, String> monkey = new HashMap<String, String>();
public static void storeDataDirector(String fileLocation,String fileName) throws Exception
{
if (fileName = monkey)
**update the "monkey map"**
}
This is my problem, also I have lot of maps and tables to be used so I wouldn't be able to use multiple if conditions and then check and update the same.
What I would like to know is the below
As I have said earlier, The file name that I am sending to the program which is "String filename" has the same name of the "Map monkey" but the former is a String and the latter is the map. I would like to know if I will be able to use the string variable as a reference to the map instance as both of them have the same name . This will highly avoid the if conditions that I am using in the program and thus I would like to possible solution for this ... Anything related to type caseting ort
You need to have another Map - whose key is a String and value is a Map. Something like Map<String,Map> allMaps = new HashMap<String,Map>()
Once you have this map , populate it with all your filenames and the corresponding maps monkey.
allMaps .put("monkey", monkey)
If a string filename corresponds to not a map but to a set , then you need to declare something more general Map<String,Object> allMaps = new HashMap<String,Object>(). Ofcourse this means you need to cast the value to its particular type before you can do any meaningful thing with it.
Then , to use this map , use your filename argument
Map monkeyAgain = allMaps.get(filename)
You can use reflection:
Storage.class.getField(fileName).get(null)
You will still have to cast the returned object. I do not think this the right approach.
The idea is to relate them in a Map, and use the file name as a key for example
Map<String, Map<String, String>>
// file store structure
If you need a generic solution, you could solve this by implementing an abstraction of your store structure, by implementing an interface similar to this one:
// T is the store type and U is the original type (String from file for instance...)
public interface StoreUnit<T, U> {
void update(U record);
List<T> list();
}
so you will have an implementation for each case (Set, Map, Table ...) and will relate it in a map using the file name as key.
monkeyFileName => MapStoreUnit<Entry<String,String>,String>
tigerFileName => SetStoreUnit<Integer, String>
elephantFileName => TableStoreUnit<Entry<Entry<String,String>,String>,String> // not sure if for Table there is something better than Entry ;)
When you wanna update some store you perform a get over the map using the file name as key, and invoking update method implemented with the record (that could be an String, complex Object) and so on. When you need to read something from there you could use the list method.

Categories