Removing key from Map in case of Atomic Values - java

I want to remove keys from map in case if the value for the key is zero(0) i am able to achieve it using map.values().removeAll(Collections.singleton(0l));.
It was working nice till i was using Map<String,Long> but now we have changed the implementation to Map<String,AtomicLong> now it dosen't remove the keys whose values are zero since i am using an Atomic variable as value.
Small code snippet on which i tried ::
Map<String, AtomicLong> atomicMap = new HashMap<String,AtomicLong>();
atomicMap.put("Ron", new AtomicLong(0l));
atomicMap.put("David", new AtomicLong(0l));
atomicMap.put("Fredrick", new AtomicLong(0l));
atomicMap.put("Gema", new AtomicLong(1l));
atomicMap.put("Andrew", new AtomicLong(1l));
atomicMap.values().removeAll(Collections.singleton(new AtomicLong(0l)));
System.out.println(atomicMap.toString());
which outputs as {Ron=0, Fredrick=0, Gema=1, Andrew=1, David=0}
as you can see the keys which have values 0 are not being removed. Can anyone suggest a solution over this , it will be of great help.
Thanks.

If you are using Java8, there is a removeIf method that you could use.
atomicMap.values().removeIf(x -> x.get() == 0L);
// Prints {Gema=1, Andrew=1}

Two instances of AtomicLong are never equal. If you look at AtomicLong you can see that it never overrides the equal() method. See Why are two AtomicIntegers never equal?
You can overcome this with your own custom AtomicLong implementation, which implements equals() and make your strategy to remove the elements work.
public class MyAtomicLongExample {
static class MyAtomicLong extends AtomicLong {
private static final long serialVersionUID = -8694980851332228839L;
public MyAtomicLong(long initialValue) {
super(initialValue);
}
#Override
public boolean equals(Object obj) {
return obj instanceof MyAtomicLong && ((MyAtomicLong) obj).get() == get();
}
}
public static void main(String[] args) {
Map<String, MyAtomicLong> atomicMap = new HashMap<>();
atomicMap.put("Ron", new MyAtomicLong(0l));
atomicMap.put("David", new MyAtomicLong(0l));
atomicMap.put("Fredrick", new MyAtomicLong(0l));
atomicMap.put("Gema", new MyAtomicLong(1l));
atomicMap.put("Andrew", new MyAtomicLong(1l));
atomicMap.values().removeAll(Collections.singleton(new MyAtomicLong(0l)));
System.out.println(atomicMap);
}
}
This will print {Gema=1, Andrew=1}

Incase if you want to compute then decide to remove when value is zero.
if (atomicMap.compute("Andrew", (k, v) -> v.decrementAndGet()) == 0) {
atomicMap.remove("Andrew");
}

Related

How to set the key-value pairs of a HashMap final in Java 11?

import java.util.HashMap;
import java.util.Map;
public class Foo {
private final Map<String, Integer> exits;
public Foo() {
this.exits = new HashMap<>();
}
public Map<String, Integer> getExits() {
return exits;
}
public void show() {
for (String i : exits.keySet()) {
System.out.println(i + ": " + exits.get(i));
}
}
}
class Bar {
public static void main(String[] args) {
Foo foo = new Foo();
foo.getExits().put("A", 1);
foo.getExits().put("B", 2);
foo.show();
//Okay, no problem.
//Output: A: 1
// B: 2
foo.getExits().replace("A", 10);
foo.getExits().remove("B");
foo.show();
//Output: A: 10
}
}
I have declared exits in class Foo as final so that it cannot be referred to another HashMap once it has been assigned in the constructor. I also want to set every elements in exits as final, so that once I put a key-value pair in exits, it cannot be modified or removed by any means. I have tried the following approach (Note the change in the getExits() method and main() method):
import java.util.HashMap;
import java.util.Map;
public class Foo {
private final Map<String, Integer> exits;
public Foo(Map<String, Integer> exits) {
this.exits = exits;
}
public Map<String, Integer> getExits() {
return new HashMap<>(exits);
}
public void show() {
for (String i : exits.keySet()) {
System.out.println(i + ": " + exits.get(i));
}
}
}
class Bar {
public static void main(String[] args) {
Map<String, Integer> temp=new HashMap<>();
temp.put("A", 1);
temp.put("B", 2);
Foo foo = new Foo(temp);
foo.show();
//Okay, no problem.
//Output: A: 1
// B: 2
foo.getExits().replace("A", 10);
foo.getExits().remove("B");
foo.show();
//Output: A: 1
// B: 2
}
}
Question 1:
Why wouldn't it work if I declared exits as private final Map<final String, final Integer> exits;?
Question 2:
Is there any other way by which I can achieve the same?
P.S: I am new to Java, so correct me if there are any mistakes since I might be mixing C++ concepts with Java.
Answer 1: Map<final String, final Integer> is not valid syntax in Java. I don't know what you mean by it. This use reminds me of const modifier in C++, but final is not const, and in any case String and Integer are already immutable
Answer 2: Your getExits method returns a modifiable copy of the map. That works, but it's more common to return an unmodifiable view of the data structure. It is a lightweight decorator that throws an exception if the caller attempts to make changes, but otherwise calls methods in the original map. The caller has to copy the map itself if it wants one.
public Map<String, Integer> getExits() {
return Collections.unmodifiableMap(exits);
}
first question:
actually in the second code when you are calling getexits everytime it returns a different shallow copy(new Hashmap).shallow copy is a different copy of exits where you can only modify the returned map,not the original one you declared at foo class. so,foo.getexits() are totally different map that you return,it is modifying new hashmap each time,not the temp one or foo(temp).if you code like this,
temp.replace("A",10);
temp.remove("B");
foo.show();
instead of,
foo.getExits().replace("A", 10);
foo.getExits().remove("B");
foo.show();
then it will print the same output as your first program does.(it will also modify).
Shortly,your second code is not modifying because everytime you are returning and modifying a new hashmap which have no relation with temp.so,those will not affect your foo(temp).
second question:
if you really want not to modify anything in the main class,then you may code like following at the getexits() method in the second program:
return Collections.unmodifiableMap(exits);
and don't change anything of the second program as you does.then it will throw
java.lang.UnsupportedOperationException
whenever you want to modify using foo.getexits() and prevent you from modifying that.but you can still modify temp separately as it has no relation with the getexits method.i am also a beginner like you,but I have tried to answer your question with my small knowledge. hope,it will help

How to create a dynamic list of custom objects associated with a flag (boolean)?

I am eventually fetching objects from my backend and I have to keep track of them. I need a collection where there are no duplicates, but every time I fetch the same object from the backend I get a new instance, so I must compare it's String key manually, I suppose.
Plus, these objects need a boolean associated with them, because they may be in this list and be "used" and I should know that later.
A typical scenario is that I have a list of 10 objecst in my collection and I fetch 8 new ones, and only 3 are new. I should add these 3 to these list and discard the 5 repeated ones.
I am about to start implementing a custom Collection for that. Is there any possibility to do it combining Pair with List, or maybe HashMap? I've been thinking on this and I couldn't come up with a conclusion.
http://docs.oracle.com/javase/7/docs/api/java/util/Set.html#add(E) Try something with a set. It allows no duplicates.
In the class of your objects, override both equals() and hashCode() to specify when two instances of your class can be considered to be the same.
If you do this, you can simply throw them into a HashSet and it will make sure that no to elements in it are the same (by the definition that you provided in the overridden methods)
Take a look at this similar question:
Implement equals with Set
For future reference, I implemented a custom class with both a list of objects and an array with my booleans. Since I had to keep both list and array synchronized, I had to iterate this list on all steps.
This is my code:
public class PromoCollection {
public static List<ParseObject> promotions = new ArrayList<ParseObject>();
public static List<Boolean> isTriggered = new ArrayList<Boolean>();
public static void add(ParseObject newObj) {
for (ParseObject p : promotions) {
if (p.getObjectId().equals(newObj.getObjectId())) {
return; // Object already in list, do not add
}
}
promotions.add(newObj); // Add new object
isTriggered.add(false); // And respective boolean
}
public static void remove(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
promotions.remove(i);
isTriggered.remove(i);
return;
}
}
}
public static void trigger(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
isTriggered.set(i, true);
}
}
}
public static boolean isTriggered(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
return isTriggered.get(i);
}
}
throw new ArrayStoreException();
}
}

Check if HashMap was modified (values added or modified)

I have a method that iterates over the HashMap to get the total integer number of all of the values. I would like to avoid iterating over the entire map and finding the sum if the HashMap wasn't changed since the last time this method was called on.
How do I check whether new values or old values were modified in a HashMap? Is there such a way?
Extend HashMap; override the methods that change values, and set a flag indicating that some value has changed. Provide a method to test this value, and probably one to reset it. Think about concurrency if it's an issue in your application.
(I am trusting that you understand how to extend a class, and that overriding the methods does not mean that you have to reimplement all of them (super is your friend). This whole class doesn't seem to me, at first glance, to be more than 30-40 lines of code.)
I add a new answer that will not be affected by clock work-around:
public class YourMap<K, V> extends HashMap<K, V> {
private int state = 0;
public YourMap() {
super();
}
#Override
public V put(K key, V value) {
state++;
return super.put(key, value);
}
public boolean isUpdated(int state) {
return (state < this.state);
}
public int getState() {
return state;
}
... // Do the same with clear, remove... methods.
}
Then in your code:
public static void Main() {
new YourMap<Integer, Integer> myMap = new YourMap<Integer, Integer>();
int state = myMap.getState();
myMap.put(1, 2);
System.out.println(myMap.isUpdated(state)); // will print true.
if (!myMap.isUpdated()) { // in this demo, it will never go in this if.
// call your process...
}
}
This one is efficient and you will not have problems you should have with currentTimeMilliseconds.

Iterator creates a new object or modifies the old one

Just a question for java gurus. If i have a code like follows
public void setSeenAttribute(String notificationId , String userId){
UserNotification userNotification = notificationRepository.getUserNotification(userId);
if (userNotification != null) {
for (Notification notification : userNotification.getNotifications()) {
if (StringUtils.equals(notification.getNotificationId(), notificationId)) {
notification.setSeen(true);
}
}
notificationRepository.createUpdateNotification(userNotification);
}
}
I want to know weather notification.setSeen(true); will make a change in the original collection or it's worthless to do something like this ? Or what can be the best practice?
In Java - "References to objects are passed by value". So, unless you explicitly reset the reference to point to another object, the current object is modified.
First of all this is not an Iterator, You are using for each loop to iterate over a collection.
And it is perfectly fine to update values while using for each loop. This is not at all allowed in "Iterator" in Java as they are call Fail-fast.
So,
notification.setSeen(true);
is updating the Object which is there in collection as new reference ie. notification is pointing to the object which resides in a collection itself.
Yes, you can do something like that as the handle is passed as a value but its reference is by object. And to prove it, here's a small example:
public class ModifyElementsOfCollection {
public static void main(String[] args) {
Collection<Wrapper<Integer>> collection = new ArrayList<Wrapper<Integer>>();
for(int i=0; i<10; i++) {
collection.add(new Wrapper<Integer>(i));
}
collection.stream().map(w -> w.element).forEach(System.out::println);
for(Wrapper<Integer> wrapper : collection) {
wrapper.element += 1;
}
collection.stream().map(w -> w.element).forEach(System.out::println);
}
private static class Wrapper<T> {
private T element;
private Wrapper(T element) {
this.element = element;
}
}
}
Before the second for loop the output are the numbers 0 through 9, afterwards they are 1 through 10. And this works for more complex stuff too.
By the way, this example uses some features from Java 8 to print the results, you could just as well use a for loop of course.

Asking about threading, arrays and cache memory

I hope in a good manner :-)
I wrote this piece of code.
What I wished to do, is to build something like "cache".
I assumed that I had to watch for different threads, as might many calls get to that class, so I tried the ThreadLocal functionality.
Base pattern is
have "MANY SETS of VECTOR"
The vector holds something like:
VECTOR.FieldName = "X"
VECTOR.FieldValue= "Y"
So many Vector objects in a set. Different set for different calls from different machines, users, objects.
private static CacheVector instance = null;
private static SortedSet<SplittingVector> s = null;
private static TreeSet<SplittingVector> t = null;
private static ThreadLocal<SortedSet<SplittingVector>> setOfVectors = new ThreadLocal<SortedSet<SplittingVector>>();
private static class MyComparator implements Comparator<SplittingVector> {
public int compare(SplittingVector a, SplittingVector b) {
return 1;
}
// No need to override equals.
}
private CacheVector() {
}
public static SortedSet<SplittingVector> getInstance(SplittingVector vector) {
if (instance == null) {
instance = new CacheVector();
//TreeSet<SplittingVector>
t = new TreeSet<SplittingVector>(new MyComparator());
t.add(vector);
s = Collections.synchronizedSortedSet(t);//Sort the set of vectors
CacheVector.assign(s);
} else {
//TreeSet<SplittingVector> t = new TreeSet<SplittingVector>();
t.add(vector);
s = Collections.synchronizedSortedSet(t);//Sort the set of vectors
CacheVector.assign(s);
}
return CacheVector.setOfVectors.get();
}
public SortedSet<SplittingVector> retrieve() throws Exception {
SortedSet<SplittingVector> set = setOfVectors.get();
if (set == null) {
throw new Exception("SET IS EMPTY");
}
return set;
}
private static void assign(SortedSet<SplittingVector> nSet) {
CacheVector.setOfVectors.set(nSet);
}
So... I have it in the attach and I use it like this:
CachedVector cache = CachedVector.getInstance(bufferedline);
The nice part: Bufferedline is a splitted line based on some delimiter from data files. Files can be of any size.
So how do you see this code? Should I be worry ?
I apologise for the size of this message!
Writing correct multi-threaded code is not that easy (i.e. your singleton fails to be), so try to rely on existing solutions if posssible. If you're searching for a thread-safe Cache implementation in Java, check out this LinkedHashMap. You can use it to implement a LRU cache. And collections.synchronizedMap(). can make this thread-safe.

Categories