I have this GWT code below which have some slight problem:
It's either the login and aboutme property is set or just the contacts is set which ever comes first in the line. Could this be that the contacts property is set before the for-loop is finished, resulting in contacts being assigned a null?
public void copyFrom(User user) {
Map<String,String> map = new HashMap<String,String>();
for (Contact contact : user.getContacts()) {
map.put(contact.getType(), contact.getValue());
}
super.set("lastlogin", user.getLastLogin());
super.set("aboutme", user.getAboutMe());
super.set("contacts", map);
}
Do I need to use a "faster" Map?
Neither a for loop, nor adding values to a Map are asynchronous operations, so that entire loop executes prior to the calls to super.set(...). The map, in this case, cannot be null, since you instantiate it at the moment of declaration. It could end up being unpopulated (for instance, if there were no elements in user.getContacts()), but not null.
Your problem lies in the implementation of set(...) by whatever super is in this case.
If you are calling get on a Map for a key which does not exist null is returned, that's true. Your code is executed sequentially, so you can be sure that your for loop is finished when you access the map.
Related
I have an ArrayList of HashMaps
ArrayList<HashMap> t = getDatabaseList();
and the data inside looks like
t=[{taskGroupID=CYQW1634868825, taskGroupName=Fitness, taskGroupColorString=#FFFF3838}, {taskGroupID=ETHC1634868825, taskGroupName=School, taskGroupColorString=#FFFFC107}, {taskGroupID=AAAA1634868825, taskGroupName=Task, taskGroupColorString=#FF00CA38}]
I am trying to use the contain method to detect if there is a Hashmap entry-set that contains the key taskGroupName with a value of Fitness. However, I have no idea exactly what to put in the method.
Something like below in pseudocode
if(t.contains(key=taskGroupName, val=Fitness)){
//run code if detected
}
I did initialize a new Hashmap variable and set the values exactly to what is found in the arraylist and passed it through the contain method just to test if it turns true and it did pass to true and ran the code when detected
ArrayList<HashMap> t = getDatabaseList();
HashMap<String,String> tempVar = new HashMap<>();
tempVar.put("taskGroupName", "Fitness");
tempVar.put("taskGroupID", "CYQW1634868825");
tempVar.put("taskGroupColorString", "#FFFF3838");
if(t.contains(tempVar)){
//detected to true and ran code
}
But if I change say the taskGroupID value of tempVar to one number different, it does not pass to true since it is not exact value and I just want to detect that there is a set with the value of Fitness for taskGroupName without caring about the rest of the values of the other categories cause those might not be the same everytime the ArrayList gets populated.
The other way solution I know at the moment is to run the for loop with the code below but I'm curious as how to achieve it with the contain method instead.
for(HashMap<String,Object> hashEntry: t){
String text = (String) hashEntry.get("taskGroupName");
if(text.equals("Fitness")){
//run code if it is Fitness
}
}
If I run the code below, the value coming from getUserName() gets appended to the list. But if I run it again, same value gets inserted again. My question is, how to make sure the value is appended only once(Unique)?
My current code
Operation operation = ListOperation.append("names", Value.get(usr.getUserName()));
Record record = client.operate( policy, key, operation );
Example: Consider the "name" bin to be a list of strings.
'LIST["T1", "T2"]'
If I add T2 again, the list should remain the same.
ListOperation.append() can take a ListPolicy, which takes flags. For write operations such as this, the ListWriteFlags have the fields ADD_UNIQUE and NO_FAIL which you should combine if you want a value to only be added if it's a new unique list element.
See https://www.slideshare.net/RonenBotzer/asug-tlvmeetup2talk
i'm assuming that ListOperation is backed by a List since the code isn't available. Assuming it is, Lists maintain order while allowing null values. Sets on the other hand only allow unique, non-null, values so this would be a perfect solution for you.
Set<String> values = new HashSet<>();
values.add("T1");
values.add("T1"); // already contains value
Alternative
If you need to maintain the order of your Collection but you want unique values, another option would be to check on add if the value already exists OR using Stream#distinct.
List<String> values = ListOperation.values.stream().distinct().collect(Collectors.toList());
If I have a class called 'TestClass' full of getters and setters, and then I set some properties on the class object in another class like so:
TestClass testClass = new TestClass();
testClass.setAppId("id");
testClass.setStatus("Status");
testClass.setMessage("Message");
List<TestClass> list = dataProvider.getList();
And then, before adding this object to my java list, I have to make sure it doesn't exist in the list to avoid duplicates.
To achieve this, I do the following check to see if all three properties of the corresponding values exist in the testClass object present in the list. If they don't, then it may be added to the list.
if(!list.contains(testClass.getAppId().equals("id")) &&
!list.contains(testClass.getStatus().equals("Status")) &&
!list.contains(testClass.getMessage().equals("Message"))) {
list.add(testClass);
}
dataProvider.refresh();
The above code is within a click handler, so is only ever executed when a button is clicked.
Why then, despite my futile attempt at stopping duplicates from entering the list, do I fail to stop duplicate records being added to my cell table in gwt?
Am I wrong in thinking the list logic is the problem?
Thank you for your help, I hope I've been thorough enough.
Your testClass.getAppId().equals("id") call returns true or false. Your list does not "contain" true or false therefore the condition becomes true and the element is added. The code should look like this:
for(TestClass testClass: list){
if(!testClass.getAppId().equals("id") &&
!testClass.getStatus().equals("Status") &&
!testClass.getMessage().equals("Message")){
list.add(testClass);
}
}
dataProvider.refresh();
testClass.getAppId().equals("id") returns true or false, weather your id equals to "id" or not. You then check if your list contains the return of this call. That's why you fail to maintain only unique items in your list.
You can create an equals/compare method in your testClass class so as to define in this function if the item that is going to be inserted already exists in your structure.
As a general approach is also better to use a hash in order to be sure that your data structure always stores unique items.
User is going to choose few items to be removed from a list.
I have two options, either pass the id of selected items or their objects' addresses in memory.
First question is that, is it a correct approach to send the objects of selected items rather than their ids?
<input type="checkbox" name="selectedItems" value="${item}"/>
rather than
<input type="checkbox" name="selectedItems" value="${item.id}"/>
If I should send the ids of items, when I pass their IDs, create an object and set the ids I am not able to remove them from the list, whats the best approach ?
Item item = new Item();
item.setID(selectedItems.get(0));
Basket basket = (Basket) session.get(Basket.class, Long.parseLong(basket_id));
basket.getItems.remove(item); <<I cant remove them by just setting their ids!!
session.update(basket);
The list.remove method removes first occurrence of the specified element from the list. Below block of code is copied from ArrayList source code:
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
// REMOVE ITEM FROM THE LIST
}
}
which uses the Object.equals method to check the equality of the object to be removed from the list. So you need to override the equals method in Item class to tell which all items are equal. And when you override equals(), you always need to also override hashCode() so the two methods are consistent
Now when passing an instance of Item to remove from the list, you need to set the values of all the properties of Item that were used to implement the equals method.
But you should not use the database identifier (id) to implement the equals(). Hibernate doesn’t assign identifier values until an entity is saved. So, if the object is added to a Set before being saved, its hash code changes (on save action) while it’s contained by the Set, contrary to the contract of java.util.Set. You could use a combination of properties, that is unique for each instance of Item.
Load item object before deleting.
Item item = session.load(Item.class, selectedItems.get(0))
then call
basket.getItems.remove(item);
There are several approaches, If you are comfortable with hql or sql, i would prefer doing it with query,
Approach one
delete from table where id in (x,y,z,xy...);
advantages: You need not load anything from the DB. You just run a sql and get the response back.
Approach two
Eager fetch the objects into the memory(Ofcoz, send the IDs from the client) iterate over the list of items and match the ID and remove it. Flush the session.
Inside your class for the object to be removed, you need to override equals() method. code it such a way that if all member variables are equal, then the objects are equal. template implementations are available in Netbeans IDE which use some more checks like the instance of check.
Otherwise object member variables could all be same but still objects
will not be equal since they refer to different locations in memory heap.
I almost invariably override equals() and toString() methods of my model classes
simple and strightforward
do not remove the copy, search inside:
for(Iterator<Item> iterator = basket.getItems().iterator(); iterator.hasNext();)
{
Item currentItem = iterator.next();
if(selectedItems.contains(currentItem.getId()))
{
iterator.remove();
}
}
however, NEVER use value="${item}" if you have not overridden item.toString().
Could you not change your ArrayList to a HashMap and store the objects against their ID's? then you can remove them with a single line of code.
Hql.
session.createQuery("delete from Item i where i.id in (:iids)").setParameter("iids", item_ids).executeUpdate();
Don't render objects directly. Don't do it. That way lies pain and madness. Suppose you do this, and haven't overridden toString():
<input type="checkbox" name="selectedItems" value="${item}"/>
Then the following happens:
You fetch items into a List, rendering each using the default class.name#address implementation of toString().
The user chooses some items to remove and submits the form, which makes a new HTTP request. The original List of items is gone, so those addresses point to...well, you have no idea what they point to.
(There are other problems: if a malicious attacker checks the page source, they now know you're running a Java-based server. No reason to volunteer that information.)
Now, you might think something like "hey, I'll just put those items in my session." Now you have the same problem: most session-handling implementations will serialize the items when storing them in the session, and deserialize them into a new copy upon retrieval. Your object references now mean nothing.
You could override toString(), but why? Just pass the IDs and send them to your DB in the removal query. That way, there are no surprises if someone decides to change the toString() implementation.
I am using Android 2.1 SDK, the application reads from the Sqlite database, a table that has two columns, an id, and a string.
I read in this into a HashMap<Long, String>, the value part of it gets displayed in a List, now, I wish to obtain the key value, so I cooked up this simple routine:
private Map.Entry<Long, String> getEntry(String sValue){
for (Iterator<Map.Entry<Long, String>> itMap = this.dbMap.entrySet().iterator(); itMap.hasNext();) {
Map.Entry<Long, String> curr = itMap.next();
if (curr.getValue().equalsIgnoreCase(sValue)) return curr;
}
return null;
}
My problem is being conscious of cpu cycles being chewed up in respect to Android, battery/cpu time, in looking for the value in the HashMap, that could be seen as a potential cycles of cpu lost.
Is there an easier and more efficient way of doing this instead of iterating?
The reasoning is that I can home in on the id, and directly delete the record from the table or even update it.
Um... it looks like the String should be the key, and the id the value. Which assumes that the Strings are unique, but so does your code.
Alternatively, can't your list keep the ID that corresponds to an entry around invisibly? This is how you'd usually do it (e.g. in Swing or in a HTML select).
Realistically, the only way to avoid having to iterate through is to keep two HashMaps (i.e. pay the memory cost) where one HashMap is the reverse of the first. You can create the reverse-lookup HashMap when you create your forward-lookup HashMap without having to loop through your data twice. That should give you low constant time access in both directions.
If you use an Adapter you can access the ID using the getItemID() method.