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.
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 2 years ago.
Improve this question
I have a question when writing a method with a number of declarations and operations, which one is better so that later on when I refer to it I will have a better grasp, or whether two of these approaches are technically the same.
-- The first approach (write all declarations before doing their operations sequentially):
Map<String, String> transferToStation1 = new HashMap<>();
Map<String, String> transferToStation2 = new HashMap<>();
transferToStation1.put(MetroUtil.LINE, line2Name);
transferToStation1.put(MetroUtil.STATION, station2Name);
transferToStation2.put(MetroUtil.LINE, line1Name);
transferToStation2.put(MetroUtil.STATION, station1Name);
var json1 = new JsonParser().parse(new Gson().toJson(transferToStation1)).getAsJsonObject();
var json2 = new JsonParser().parse(new Gson().toJson(transferToStation2)).getAsJsonObject();
station1.add(MetroUtil.TRANSFER, json1);
station2.add(MetroUtil.TRANSFER, json2);
-- The second approach (as soon as declaring a variable, write all of its operations):
Map<String, String> transferToStation1 = new HashMap<>();
transferToStation1.put(MetroUtil.LINE, line2Name);
transferToStation1.put(MetroUtil.STATION, station2Name);
Map<String, String> transferToStation2 = new HashMap<>();
transferToStation2.put(MetroUtil.LINE, line1Name);
transferToStation2.put(MetroUtil.STATION, station1Name);
var json1 = new JsonParser().parse(new Gson().toJson(transferToStation1)).getAsJsonObject();
station1.add(MetroUtil.TRANSFER, json1);
var json2 = new JsonParser().parse(new Gson().toJson(transferToStation2)).getAsJsonObject();
station2.add(MetroUtil.TRANSFER, json2);
The general recommendation is to declare variables as late as possible, or as close as possible to their usage.
In other words, don’t pre-declare variables up-front. Instead, initialise and use them immediately after their declaration.
Thus, the second way is better.
That being said, having essentially the same code duplicated for different variables is also a potential code smell that might benefit from refactoring the remove the redundancy. And having variables named thing1 and thing2 is almost never a good idea, and indicates that you might want to use an array, or a loop, or both.
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 3 years ago.
Improve this question
I have a piece of code that takes in an ArrayList<String> object and eventually takes that object and adds it to a HashMap object as the key. When I print the hashmap, the key's are all null while the values are correct.
I already know I can fix the code by passing in a copy of the ArrayList<String> object and that fixes my issue (i.e. buildHash(new ArrayList<String>(key)). But why does it point to null otherwise?
HashMap<ArrayList<String>, ArrayList<String>> hash = new HashMap<>();
ArrayList<String> key = new ArrayList<String>();
for (int i = 0; i <= 9999999; i++) {
key.add(//different strings depending on the iteration);
if ( !hash.contains(key) ) {
buildHash(key);
}
key.clear();
}
private void buildHash(ArrayList<String> key) {
ArrayList<String> follows = new ArrayList<String>();
for (int index = 0; index <= 9999999; index++) {
// add stuff to follows...
}
hash.put(key, follows);
}
I thought that the value of the key would be added to the hash, and the hash's keys would point to the value it was before it was cleared by key.clear(). That way I could reuse key over and over without creating another object in memory.
I'm new to Java (and coding) so I'm probably naive, but I thought I could save memory by utilizing the mutability of ArrayLists as opposed to Lists as the number of operations and key's generated for this project are well into the millions, if not more. Is there no avoiding that? And if not, is there any other optimization I could do?
As documented, ArrayList::clear removes all elements from the list. So you are wiping out the content.
utilizing the mutability of ArrayLists
Exactly what you do not want in a key. An object used as a key in a map should never be modifiable, not in a way that affects the outcome of the hash value calculation or affects the outcome of the equals method. Would you expect to find someone in a phone book after they changed their name?
It hard for me to imagine where you would ever want to use a list as a key in a map.
As for trying to “save memory”… don’t. The last thing a new programmer should worry about is conserving RAM. Write simple code, easy to read, easy to edit. Then let the JVM do the optimizing work for you.
I suggest you not try so hard at being clever. Spend some time looking at other code. Search Stack Overflow and elsewhere to find code similar to your logic problem or the classes you are using. Then study code samples.
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 9 years ago.
Improve this question
I've been thinking about the naming of three methods in the famous Map class. To get all keys in the map we use keySet(), for entries there is entrySet() and for values the values() method is used.
What I find a bit peculiar is that the first two methods includes the returned type (set) in the name. Wouldn't it be nicer to exclude it? That would mean that the method names would be harmonized and it would look quite nice (imho!):
keys()
entries()
values()
The other alternative would be to suffix the values() method:
keySet()
entrySet()
valueCollection()
To me this doesn't look as good and makes the code ugly.
This is a philosophical question as changing the method naming would break the backward compatibility.
Any thoughts on the topic?
The main intention of having the Set is to signify that the returned collection would have the characteristics of Set (i.e) it will not contain any duplicates.
And since values() like the others, returns a Collection(mind you, keySet and entrySet also return a collection, but a specific one, Set), it would quite trivial to include the collection word in the method name.
Keeping method names as keySet or entrySet shows your intent that you are returning a Set and committing to the characteristics of Set namely no duplicates.
On keeping names as keys or entries you should return a Collection or Iterable so that shows the intent that the implementation has not committed to any particular type of Collection and that may change in future.
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 9 years ago.
Improve this question
Is order still guaranteed when the map objects are accessed as shown below at location 1 and 2?
//....
public void firstMethod(){
Map<K,V> sortedMap=new LinkedHashMap<K,V>();
sortedMap.put(h,g);
//....
Map<K,V> anotherMap=someOtherMethod(sortedMap);
// order of anotherMap when read ...2
}
public Map<K,V> someOtherMethod(Map<K,V> someMap){
someMap.put(a,b);
//order of someMap when read ...1
//.....
return someMap;
}
//....
If the concrete instance of your Map object is a LinkedHashMap yes. It does not matter what you do with it. The object will keep it's data ordered and the implementation does not change if you cast to just Map or even Object or pass it to methods. It will stay internally a LinkedHashMap. You might no longer see that it is one if you cast it to Object.
Assuming that you don't know the source code, the only thing that is not guaranteed is that someOtherMethod returns your LinkedHashMap. It could also re-order it.
A method should not be trusted unless it specifies those things. But since you know the sourcecode here, you have the guarantee that it is your LinkedHashMap in perferct order.
As per the docs:
Hash table and linked list implementation of the Map interface, with predictable iteration order.
So even after things are inserted and removed, the order should persist through whatever you want to do to it.
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());