Maybe this is trivial question for experienced programmers but i wonder if there is any significant performance difference (with big or very big amount of data in collection) between two difference approaches of passing variables?
I've made a tests but with rather small data structures and i don't see any significant differences. Additionally i am not sure if these differences aren't caused by interferences from other applications run in background.
Class with collection:
public class TestCollection
{
ArrayList<String[]> myTestCollection = new ArrayList<String[]>();
public TestCollection()
{
fillCollection();
}
private void fillCollection()
{
// here is fillng with big amount of data
}
public ArrayList<String[]> getI()
{
return myTestCollection;
}
}
And methods that operate on collection:
public class Test
{
static TestCollection tc = new TestCollection();
public static void main(String[] args)
{
new Test().approach_1(tc);
new Test().approach_2(tc.getI());
}
public void approach_1(TestCollection t)
{
for (int i = 0; i < tc.getI().size(); i++)
{
// some actions with collection using tc.getI().DOSOMETHING
}
}
public void approach_2(ArrayList<String[]> t)
{
for (int i = 0; i < t.size(); i++)
{
// some actions with collection using t.DOSOMETHING
}
}
}
Regards.
No, there is no real difference here.
Java passes object references to methods, not copies of the entire object. This is similar to the pass by reference concept in other languages (although we are actually passing an object reference to the called method, passed by value).
If you come from a C programming background it's important to understand this!
And, some tips - firstly, it's better practise to declare your list as List<...> rather than ArrayList<...>, like this:
List<String[]> myTestCollection = new ArrayList<String[]>();
And secondly, you can use the improved for loop on lists, like this:
// first case
for (String[] s : tc.getI()) { /* do something */ }
// second case
for (String[] s : t) { /* do something */ }
Hope this helps :)
Related
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();
}
}
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.
I'm trying to create a simple method which I have below:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
if (data.equals("action1")) {
// call a method on a value
}
if (data.equals("action2")) {
// call a different method on a value
}
}
This is only a small snippet (I took a lot out of my code), but essentially I want to be able to call a specific method without testing multiple lines in my for loop for which method to call.
Is there a way for me to decide what value to call by declaring a variable at the very beginning, instead of doing so many 'if statement' tests?
OK, I have an ArrayList inside my class:
private List<Value> values;
The value object has 2 fields time and speed.
Depending on the string I pass (time or speed), I want to be able to call the specific method for that field without doing multiple string comparisons on what method I passed.
For example, I want to be able to call getSpeed() or getTime() without doing a string comparison each time I want to call it.
I just want to test it once.
Another one:
enum Action {
SPEED {
public void doSomething() {
// code
}
},
TIME {
public void doSomething() {
// code
}
};
public abstract void doSomething();
}
public void analyzeWithAnalytics(Action data) {
for (int i = 0; i < VALUE; i++) {
data.doSomething();
}
}
You can have a Map which maps the names (action1, action2, ...) to classes which common parent and one method. And make call as following:
map.getClass("action1").executeMethod();
Map<String, MethodClass> theMap = new Map<>();
interface MethodClass {
executeMethod();
}
and children:
class MethodClass1 implements MethodClass{...}
class MethodClass2 implements MethodClass{...}
Your goal is not really clear from your question. Do you want to:
avoid typing the many cases?
gain code readability?
improve performance?
In case you're after performance, don't optimize prematurely! Meaning, don't assume that this will be important for performance without checking that out first (preferably by profiling). Instead focus on readability and perhaps laziness. ;)
Anyway, you can avoid the many tests inside by simply checking data outside of the loop. But than you'd have to copy/paste the loop code several times. Doesn't make the method more beautiful...
I would also recommend using case instead of if. It improves readability a lot and also gives you a little performance. Especially since your original code didn't use if - elseif - ... which means all conditions are checked even after the first was true.
Do I get this right? data will not be changed in the loop? Then do this:
public void analyzeWithAnalytics(String data) {
if (data.equals("action1")) {
for (int i = 0; i < VALUE; i++) {
// call a method on a value
}
} else if (data.equals("action2")) {
for (int i = 0; i < VALUE; i++) {
// call a different method on a value
}
}
}
You can also switch on strings (Java 7) if you don't like ìf...
You could try something like this, it would reduce the amount of typing for sure:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
switch(data) {
case "action1": doSomething(); break;
case "action2": doSomething(); break;
}
}
}
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.