Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Following situation:
I've created some methods, that allow me to manipulate a List. For a simple example these methods are addSomeElements(...) and removeSomeElements(...)
What is the best approch to call those methods? I know following ways to do that, but don't know which one's the best?!
1) re-initialize the list
private void doSomething(List<String> list) {
list = addSomeElements(list);
list = removeSomeElements(list);
}
In this case the methods would of course have to return a list:
private List<String> addSomeElements(List<String> list) {
list.add(...);
return list;
}
2) create new variables
private void doSomething(List<String> list) {
final List<String> list2 = addSomeElements(list);
final List<String> list3 = removeSomeElements(list2);
}
private List<String> addSomeElements(List<String> list) {
final List<String> newList = new ArrayList<String>(list);
newList.add(...);
return newList;
}
3) work with void methods
private void doSomething(List<String> list) {
addSomeElements(list);
removeSomeElements(list);
}
private void addSomeElements(List<String> list) {
list.add(...);
}
This would be the easiest way, but I don't really like it, because I think for the user it's not always obvious what you're doing. If you have an int for example, you would declare it like int myInt = 0. When you want to change the value, you could just say myInt = 1. It's clear that myInt has now a new value. But with the list it's different. The list you want to change might just be one of several parameters of the method you wanna call to modify the list. The user may probably not recognize that you've modified the list, which seemed to be only a Parameter, if the naming of the method doesn't tell it.
What would be the "cleanest" approach here?
If you're modifying the list passed into your method, don't return the list reference (your option #1 and option #2 since edited); it gives the impression at the API level that you're creating a new list, not modifying the one you were given.
That leaves you with two choices, either of which is "best practice" depending on context:
Modify the list passed in, and use void methods (or methods that return something else entirely if appropriate). (This is your option #3.)
Create new lists with the additions/removals, and return a reference to the new list. (This is like your edited option #2, but note that you would also have to return list3 out of doSomething for it to make sense.)
I recommend creating new lists instead of manipulating existing instances. Working with immutable state (which means copying state instead of modifying state) generally leads to cleaner code and less bugs. So I recommend going on the 2) way.
The mutable approach (modifying an existing list) may be faster, but don't go this way unless you have a very good reason to optimize.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I have a HashMap that i need to send to 2 methos, each method might add entries to it, I return the HashMap afterwards. What is the more clean approach to this:
public HashMap<String, Boolean> getDataMap() {
HashMap<String, Boolean> resultMap = new HashMap<>();
gatherData1(resultMap);
gatherData2(resultMap);
return resultMap;
}
or
public HashMap<String, Boolean> getDataMap() {
HashMap<String, Boolean> resultMap = new HashMap<>();
resultMap = gatherData1(resultMap);
resultMap = gatherData2(resultMap);
return resultMap;
}
What approach is cleaner, in the second example it is more obvious that the 2 methods are there for operating on the input and returning a result so it is more readable but also maybe its not so usefull or even confusing for some. Im just interested in a proper way of doing things especially since this can get a lot more complex and as a result a lot harder to read and understand by other people
There is a major difference between the two snippets. The second one can return a new Map, that may or may not contain the data that was originally in the resultMap.
The first one can only mutate the input parameter, and it is a topic open for discussion wether or not methods are allowed to modify the input. Imho they should not, they should operate on the input and return output, end of story.
Therefore I would recommend / prefer the second snippet including modifying the gatherData implementation to not mutate the passed map but instead return a new one. You may even not pass resultMap in at all but instead just return a completely new map and make the merging / combining of the resultMap and the the return value of gatherData part of the getDataMap implementation. That should be the implementation if gatherData does not actually need the Map for some internal logic.
If this is just for config purposes and the gatherData methods are very simple, do not have a lot of logic or not much else happens to the resultMap then it may be fine to modify the input parameter.
If the method does not copy the map, but only adds entries (or removes or updates entries), then there is simply no need to return the map, as the reference to the map is the same across the caller and callee methods. It's not a matter of readability but more of avoiding redundant reassignment. If the method otherwise creates a new copy, then you'd have the return new map.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Just took a quiz in a CS course I'm in, and I wanted to compare my thoughts with what you guys know. The question asked "Which of the following data structures can be stepped through with an Iterator?" and the options were "ArrayList, an array-based implementation of the QueueADT, and an array-based implementation of the StackADT." You could select more than one, but I only selected ArrayList -- I thought that iterators could only step through Object data structures, and since the ADTs were implemented using arrays, an Iterator couldn't be used on them. Is my thinking incorrect here?
The question is a bit, eh... unclear.
The for-each sense
If the sense is 'what can you use the for-each construct on', then the answer is: instances of Iterable, and arrays:
int[] a = new int[10];
for (int b : a) { .... }
is legal, even though a is not iterable. An Iterable is defined as: has the method public Iterator iterator() { .. }. So Iterators aren't iterable, but something like ArrayList implements Iterable.
In that sense, arrays are a lot like iterables: You can step through them. Just, not with an iterator, unless...
The 'an iterator could be made' sense
Hey, I can make ya an iterator that iterates over an array, no problem:
String[] arr = new String[10];
return new Iterator<String>() {
private int idx = 0;
public boolean hasNext() { return idx < arr.length; }
public String next() { return arr[idx++]; }
};
So, can you iterate through an array using an iterator? I guess so. Only took 5 lines.
The 'array-based' doesn't mean 'array' interpretation
ArrayList is an array-based implementation of List. Hence the name ArrayList. It is iterable and will return iterators. That implementation looks a lot like what I wrote in the previous section.
Assuming QueueAdt is a reference to this - then QueueADT is analogous to List (an interface that just defines operations), and "an array-based implementation of QueueADT" would then be analogous to ArrayList. However, one crucial difference is that the List interface itself demands that any implementation is Iterable<T>, whereas the QueueADT interface doesn't require this, assuming I linked to the right code. Nevertheless, implementations (subtypes) can add extra features if they want. This is perfectly legit:
public class ArrayQueueAdt<T> implements QueueADT<T>, Iterable<T> {
private final Object[] array;
#Override public Iterator<T> iterator() {
// something like the above
}
public void enqueue(T element) {
// impl here
}
// etcetera
}
In the 'arrays are Iterators or Iterable' sense
Then no. Arrays do not implement Iterable, and they do not have an iterator() method. The idiomatic java way to turn an array into an iterable or iterator is: Arrays.asList(theArray), which is lightweight (doesn't copy anything) and is Iterable. Arrays.asList(theArray).iterator() similarly, is a lightweight (no copies) way to get it. So, maybe?
They don't HAVE to (because QueueADT doesn't declare it, whereas List does).
So, the answer is pretty much ¯\(ツ)/¯ I guess yes, because the answer in all these senses is yes, or maybe.
This question already has answers here:
Is it a bad practice to add elements to List using getter method in java?
(6 answers)
Closed 5 years ago.
You have an object that contains a list:
public class MyPojo {
private List<Object> list;
}
And you want to add an item to this pojo's list.
What's better ?
1) You add a getter, get the list and add an object to it
public class MyPojo {
private List<Object> list;
public List<Object> getList() {
return list;
}
}
// and then use
new MyPojo().getList().add(Object);
2) You write a addItem() in your Pojo that insert the object to the list
public class MyPojo {
private List<Object> list;
public void addItem(Object item) {
list.add(item);
}
}
// and then use
new MyPojo().addItem(Object);
What is the best pratice for code quality in this case ?
Thanks !
If you've the freedom to choose, always prefer the second way, i.e., calling the method which internally modifies the instance field.
In the first one, you're clearly exposing the List<Object> instance field, which is a very poor way of coding. You should never adopt that.
All answers will be opinionated. I think that #1 breaks encapsulation, so I'd go for #2. However, I would do this only for domain objects, i.e. I wouldn't do it for data transfer objects (DTO's) or any other datavalue.
Say you chose the first method, which modifies the internal representation of the class without its knowledge. A lot of client code is written that modifies the list.
Later, you change the class in such a way that you need to know if the list has been modified. Or maybe you want to change the internal representation. But now there's all this external code that violates encapsulation. It's going to be either more expensive or infeasible to modify the external code, depending on whether or not you can modify it.
The second method encapsulates the data. You leave the door open to changing the internal representation, or monitoring changes.
This question already has answers here:
Merge two lists in constant time in Java
(4 answers)
Closed 9 years ago.
I have two LinkedList in my code and I need to make one that have both. I will not need this Lists anymore, just the new one, which have all data I need.
I could use .addAll(), but performance is I huge issue and I cant wait to copy,adding references, everything every time..
I am looking for something like we normally do if we create our own linkedlist, just connect the last node from one to the fist from the second.. Is there a way to do that using the LinkedList class from the java api?
Merging collections is a different case, although the operation means almost the same, my issue is just regarding performance and just for linkedlists, which normally can do what I need. Also "merging" is kind of an ambiguous term, what I want is just to put then together no matter what order they are, with performance in mind.I am not looking if is possible to merge...
Another thing, my question is just regarding the API, I am not looking for building my own code (boss requirement) and that is why is different from this one: Merge two lists in constant time in Java - not useful answers there either..
If you are using LinkedList then you are most likely not interested in indexed access (since indexed access is slow... but keep in mind that a list only stores references, so for very large lists with few insert/removes you are going to be more memory efficient with an ArrayList as it doesn't need to allocate each node on the heap)
So what you actually want is something that gives you most of the List contract... or maybe not even that.
It could well be that all you want is something that gives you Iterable<String>... if that is the case then you have a very easy life:
public class UberIterable<T> implements Iterable<T> {
private final List<List<T>> lists;
public UberIterable(List<T>... lists) {
this.lists = Arrays.asList(lists);
}
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<List<T>> metaNext = lists.iterator();
Iterator<T> next;
public boolean hasNext() {
while (true) {
if (next != null && next.hasNext()) return true;
if (metaNext.hasNext()) next = metaNext.next(); else return false;
}
}
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return next.next();
}
public void remove() {
throw new UnsupportedOperation();
}
}
}
}
That is a basic implementation that will give you a merged view of many lists. If you want to get more of the contract of List you could repeat the same tricks only with a better implementation of ListIterator which will get a lot of what you are probably after, or finally by extending AbstractList and overriding the appropriate methods with your new ListIterator implementation
If you only want to iterate over the new list and you can replace List with Iterable you can use Guava's Iterable.concat as described here:
Combine multiple Collections into a single logical Collection?
I'm afraid the answer is no. The internal Entry class used by LinkedList is private, and all the public methods exposed by LinkedList work with general collections.
Your use case seems reasonable to me, but this implementation doesn't support it.
I'm afraid that the only way to do this is by using reflections... When you take a look at the source code of LinkedList, you can see that the subclass Entry<E> is private, which is a problem if you want to connect the first and last entries to other entries, in order to merge the list.
Update: Even reflections are not safe (unless you add checks), because Oracle changed the name of the subclass Entry to Node and changed the order of arguments of the constructor! in JDK 7, which is stupid IMHO.
Dirty solution: Do a whole copy paste of the source code and change the private keywords to public. However, I'm not sure this is allowed by Oracle. Check their license.
One way you could go about doing this is by using getLast() to grab the last element off the one of the lists and then use addFirst() on the other in order to add it to the front.
As has been said here, however, addAll() would not be copying anything and could be used just as easily.
If your issue is with the actual instantiation of node objects in the LinkedList, you may need to implement your own version that exposes more of the implementation mechanisms in its API.
why not create a wrapper/proxy class that implements List and contains references to the 2 sublists, then implement the List methods (or at least the ones you need downstream) - a little bit of work but if copying either of the lists is really the issue sounds like it is worth it.
import java.util.LinkedList;
public class MergeLinkedList {
public static void main(String[] args) {
LinkedList<String> mainlist = new LinkedList<String>() ;
mainlist.add("A");
mainlist.add("B");
LinkedList<String> secondlist = new LinkedList<String>() ;
secondlist.add("C");
secondlist.add("D");
mainlist.addAll(secondlist);
System.out.println(mainlist);
}
}
O/P
[A, B, C, D]
you have to use addall();
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
In my code I have a pretty big loop and I need to create a new variable at the end of each iteration (integers). Is this possible? I read about a ScriptEngineManager class, but I'm not sure if this will be able to help. I suppose I could create a bunch of integers equal to 0, but I'm not exactly sure how many times I will need to create a new variable (it depends on the conditions of the loop). Hopefully this makes sense.
Use an array. In Javascript, place var results = [] before your loop and append results using results.push(value). In Java, you'll want to use an ArrayList. (Those are very different languages, by the way.)
Hopefully this makes sense.
Unfortunately, it doesn't.
In Java it makes no sense to create variables on the fly. It is extremely difficult to do, and once you have done it they are extremely difficult to use. (By contrast, it is easy to do in Javascript ...)
However, this just means that you need to do what you are trying to in a different way. For instance, the following does a computation in a loop and then saves the results in an (existing) ArrayList variable:
List<Integer> results = ArrayList<Integer>();
while (...) {
// Do computation ...
int result = ...
results.add(result);
}
// Now we have all of the results in 'results'
Or, if you want to bind each of the results to a distinct name, you could do something like this:
Map<String, Integer> results = HashMap<String, Integer>();
while (...) {
// Do computation ...
String name = ...
int result = ...
results.put(name, result);
}
Following is the way that i have implemented and helped me to fix my solution easily without much hurdles.
// Creating the array List
List accountList = new ArrayList();
for(int k=0;k < counter;k++){
accountList.add(k, (String)flowCtx.getValueAt("transitId"+m));
}
Iterating the loop and adding the objects into the arraylist with the index.
//Retrieving the object at run time with the help of the index
String a = accountList.get(i));
No, It is not possible to declare variables in java at runtime. But java provides java.util.map, which can be used like in the example below. We can assume that the key is the variable name.
Map<String, Object> declareVariableRuntime= new HashMap<String, Object>(); declareVariableRuntime.put("variableName", new Object());