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.
Related
My current code looks something like this:
public void myMethod()
{
instance1.myPanel.setVisible();
instance2.myPanel.setVisible();
instance3.myPanel.setVisible();
instance4.myPanel.setVisible();
//A bunch more
instance57.myPanel.setVisible();
}
Is there a ways to shorten it?
The Code below obviously doesn't work but gives you an idea of what I'm trying to do:
public void myMethod2(myClass instance1)
{
instance1.myPanel.setVisible();
}
int i = 1;
while(i <= 57)
{
myMethod2("instance" + i);
i++
}
In practice, this kind of problem is normally handled using some sort of collection, and its use will often fit naturally into the initialization of a program with a large number of objects. Rather than hand-writing the creation of 57 similar objects, one line at a time, you would create them in a loop, adding them to a collection as you do so.
A List implementation like ArrayList would be a good choice here, or one could simply use an array.
With a List:
/* During initialization of your program somewhere. */
List<MyClass> instances = new ArrayList<>();
for (int i = 0; i < 57; ++i) {
instances.add(new MyClass());
}
...
/* Later when you need to invoke a method: */
instances.forEach(instance -> instance.myPanel.setVisible());
You can build a list of your vars and just go through them:
List<ClassType> list = Arrays.asList( obj1, ob2, obj3 );
list.forEach( instance -> instance.myPanel.setVisible() );
I would like to model a graph, and to do so :
I have a class A that contains a LinkedList of instances of A and has a setter method associated :
class A {
private LinkedList<A> list;
[...]
public setList(LinkedList<A> l) {
this.list = l;
}
}
And in an other class NetA I have a method genCon that takes a LinkedList of instances of A then sets their list attribute to be a shuffled SubList of rlist :
static void genCon (LinkedList<A> rlist) {
for(int i=0; i<rlist.size(); i++) {
A temp = rlist.get(i);
LinkedList<A> slist = new LinkedList<A>(rlist.subList(0, rlist.size()));
temp.setList(slist);
}
}
Then genCon(rlist) is called in main, but altough all the objects of rlist should have their list initialized (and being equal to a shuffled version of rlist) some appear to be empty, with no consistent pattern (i.e. not every n or repeatable pattern), but completely at random.
At first I thought that A temp = rlist.get(i) was not giving me a shallow copy of the object at index i, but the check for identity with == returns true, so, if I am not mistaken that means that both variable hold the same reference and that should not be what is causing the issue?
Then I thought that it might be an optimization issue, maybe eclispe tries to do the operations in parallel and that somehow messes up the initialization at random?
I have tried to process step by step, but I can't seem to find where I messed up.
What did I miss?
Edit :
The main function looks like this :
public static void main(String[] args) {
LinkedList<A> a_list = generateAList(20);
genCon(a_list);
for(int i=0; i<a_list.size(); i++) {
System.out.println(a_list.get(i).toString());
}
}
a_list is correctly initialized. The issue happens in the following loop, when trying to print the objects.
Since it's only for testing main is located in the same class as genCon() atm.
generateAList() looks like this :
static public LinkedList<A> generateAList(int n) {
LinkedList<A> a_list = new LinkedList<A>();
for(int i=0; i<n; i++) {
ap_list.add(A.rand()); // A.rand() is just a static function that return an instance of A with randomly set values and an unitialized list.
}
return ap_list;
}
In my program, I want to create multiple threads in one of the methods where each thread has to run a specific method with a given input. Using Runnable, I have written this snippet.
class myClass {
public myClass() { }
public void doProcess() {
List< String >[] ls;
ls = new List[2]; // two lists in one array
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
// create two threads
Runnable[] t = new Runnable[2];
for (int i = 0; i < 2; i++) {
t[ i ] = new Runnable() {
public void run() {
pleasePrint( ls[i] );
}
};
new Thread( t[i] ).start();
}
}
void pleasePrint( List< String > ss )
{
for (int i = 0; i < ss.size(); i++) {
System.out.print(ss.get(i)); // print the elements of one list
}
}
}
public class Threadtest {
public static void main(String[] args) {
myClass mc = new myClass();
mc.doProcess();
}
}
Please note, my big code looks like this. I mean in one method, doProcess(), I create an array of lists and put items in it. Then I want to create threads and pass each list to a method. It is possible to define the array and lists as private class members. But, I want to do that in this way.
Everything seems to be normal, however, I get this error at calling pleasePrint():
error: local variables referenced from an inner class must be final or effectively final
pleasePrint( ls[i] );
How can I fix that?
The reason you are getting this error is straightforward and clearly mentioned - local variables referenced from an inner class must be final or effectively final. This is, in turn, because, the language specification says so.
Quoting Guy Steele here:
Actually, the prototype implementation did allow non-final variables
to be referenced from within inner classes. There was an outcry from
users, complaining that they did not want this! The reason was interesting: in order to support such variables, it was necessary to
heap-allocate them, and (at that time, at least) the average Java
programmer was still pretty skittish about heap allocation and garbage
collection and all that. They disapproved of the language performing
heap allocation "under the table" when there was no occurrence of the
"new" keyword in sight.
As far as your implementation goes, instead of using an array of list, I'd rather use a list of lists.
private final List<List<String>> mainList = new ArrayList<>();
You can create new lists and insert them into the main list in the constructor depending on the number of lists you want.
public ListOfLists(int noOfLists) {
this.noOfLists = noOfLists;
for (int i = 0; i < noOfLists; i++) {
mainList.add(new ArrayList<>());
}
}
You can then change your doProcess() method as follows:
public void doProcess() {
for (int i = 0; i < noOfLists; i++) {
final int index = i;
// Using Lambda Expression as it is much cleaner
new Thread(() -> {
System.out.println(Thread.currentThread().getName());
pleasePrint(mainList.get(index)); // Pass each list for printing
}).start();
}
}
Note: I used an instance variable named noOfLists to (as the name suggests) store the number of lists I need. Something as follows:
private final int noOfLists;
To populate the list, you could do:
mainList.get(0).add("1");
mainList.get(0).add("2");
mainList.get(0).add("3");
mainList.get(1).add("4");
mainList.get(1).add("5");
mainList.get(1).add("6");
// And so on...
And you'll get the output something as:
Thread-0
1
2
3
Thread-1
4
5
6
Hope this helps :)
First to that, you will get a NullPointerException here:
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
Before, yo must instantiate the lists:
ls[0] = new ArrayList<>();
ls[1] = new ArrayList<>();
About the compiler error, try to define the array as final. Change:
List< String >[] ls;
ls = new List[2]; // two lists in one array
By:
final List< String >[] ls = new List[2]; // two lists in one array
This is because you can't access to non-final (or effectively final) variables from a local class.
'ls' is effectively final but probably, since you have defined it in two lines, the compiler is not able to notice that.
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();
}
}
I'm fairly confident that there's no way this could work, but I wanted to ask anyway just in case I'm wrong:
I've heard many times that whenever you have a certain number of lines of very similar code in one batch, you should always loop through them.
So say I have something like the following.
setPos1(getCard1());
setPos2(getCard2());
setPos3(getCard3());
setPos4(getCard4());
setPos5(getCard5());
setPos6(getCard6());
setPos7(getCard7());
setPos8(getCard8());
setPos9(getCard9());
setPos10(getCard10());
setPos11(getCard11());
setPos12(getCard12());
There is no way to cut down on lines of code as, e.g., below, right?
for (i = 0; i < 12; i++) {
setPos + i(getCard + i)());
}
I'm sure this will have been asked before somewhere, but neither Google nor SO Search turned up with a negative proof.
Thanks for quickly confirming this!
No way to do that specifically in Java without reflection, and I don't think it would be worth it. This looks more like a cue that you should refactor your getcard function to take an integer argument. Then you could loop.
This is a simple snippet that shows how to loop through the getters of a certain object to check if the returned values are null, using reflection:
for (Method m : myObj.getClass().getMethods()) {
// The getter should start with "get"
// I ignore getClass() method because it never returns null
if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
// These getters have no arguments
if (m.invoke(myObj) == null) {
// Do something
}
}
}
Like the others stated, probably it's not an elegant implementation. It's just for the sake of completeness.
You could do it via reflection, but it would be cumbersome. A better approach might be to make generic setPos() and getCard() methods into which you could pass the index of the current item.
You need to ditch the getter/setter pairs, and use a List to store your objects rather then trying to stuff everything into one God object.
Here's a contrived example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Foo {
public static class Card {
int val;
public Card(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
public static class Position {
int value;
public Position(Card card) {
this.value = card.getVal();
}
}
public static void main(String[] args) {
List<Card> cards = new ArrayList<Card>(Arrays.asList(new Card(1), new Card(2), new Card(3)));
List<Position> positions = new ArrayList<Position>();
for (Card card : cards) {
positions.add(new Position(card));
}
}
}
You can't dynamically construct a method name and then invoke it (without reflection). Even with reflection it would be a bit brittle.
One option is to lump all those operations into one method like setAllPositions and just call that method.
Alternatively, you could have an array of positions, and then just loop over the array, setting the value at each index.
Card[] cardsAtPosition = new Card[12];
and then something like
public void setCardsAtEachPosition(Card[] valuesToSet) {
// check to make sure valuesToSet has the required number of cards
for (i = 0; i < cardsAtPosition.length; i++) {
cardsAtPosition[i] = valuesToSet[i];
}
}
Reflection would be your only option for your example case.