How to overcome the fact that primitives are passed by value - java

I have a long piece of code that calculates two values (doubles) for me, I use this piece of code in a few places - to stick with DRY principles I should refactor this bit of code to a nice unit testable method. However I cant make it return two doubles, and doubles are primitive so cannot be passed by value and manipulated. The cleanest way I can think of doing this is by making this method return an double[]. Can anyone think of a better way?
Thanks

Firstly, all variables are passed by value in Java, not just primitives. It's just that objects can be mutable. It's important to understand that. For example:
public void addHour(Date date) {
date.setTime(date.getTime() + 3600 * 1000);
}
The date is passed by value but Date is mutable so it can be modified but try and do this:
public void addHour(Date date) {
date = new Date(date.getTime() + 3600 * 1000);
}
and it won't change the date. Why? Because date is a reference but is passed by value.
Secondly, do these doubles relate to each other in some way? If so wrap them in a class than describes this relationship like:
public class Coordinate {
private final double x;
private final double y;
public Coordinate(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() { return x; }
public double getY() { return y; }
}

You could encapsulate them in a class for this purpose.
You could also give a double[] parameter to the method that calculates them and where it will put the calculated values in. This can be rather efficent as the caller code can reuse this array for successive invocations if performance is important.

A class (immutable) with two double fields? Might even want to add some interesting methods to the class.
The other way around is to have the method take a callback object.

double[] arr = {val1, val2};
return arr
or go with a Pair-like class that encapsulates 2 values...

If the two doubles can be thought of as a logical pairing of values, then it might make sense to bundle them in a simple object?

I'm more of a C++ guy, but creating an object of your own called Pair which can hold 2 doubles and can be passed by reference makes sense to me.

Create an new class that has two double properties with getters and setters and constructor if you like (and equals and hashcode...) and make the method return that type of object. A generic way to do that would be a Pair class. This is a common pattern and you should find code snippets everywhere (e.g. in the netbeans code base).

You have several options:
Return an array
Return a List<double>
Return an object of a class that wraps your two doubles
And by the way, Java does not pass objects by reference. It passes pointers to objects by value.
http://javadude.com/articles/passbyvalue.htm

A double array is the most obvious answer. You can make it a bit safer by having a wrapper object like this:
public class MyTwoDoubles {
public MyTwoDoubles(double one, double two) { ... }
public double getOne() { ... }
public double getTwo() { ... }
}

You can rather use Wrapper classes which are of reference types
For every value type you can find a wrapper class.
for your case java.lang.Double can be used,hope this solves the purpose
But still as a good design i suggest you not to alter the object value inside the method.
Instead refactor the code in such a way you call it twice and return two different values then assign it to the original.
As a good practice its not advisible to alter object value inside a method

Related

Java: Mapping array elements to a set of properties

I have multidimensional double[][] arrays of which each element has a set of properties.
I designed these properties as a Class:
public class ElemProperties
{
public double prop1;
...
}
Linking them with the elements of the array using a HashMap:
HashMap<double[][], ElemProperties> elemProperties;
using it like e.g:
elemProperties.get(exampleArray).getProp1();
However, this only serves as a mapping between the whole array and properties. What I'm trying to do is to actually map the elements. Since Java doesn't have pointers, I'm kind of stuck at this position. This design seems very convoluted is there a better way to achieve this goal?
First attempt would be:
public class Elem {
private double value;
private double additionalProperty1;
private double additionalProperty2;
...
}
And create an Elem[][] instead of a double[][].
This at least works but multi-dimensional arrays aren't too efficient and aren't too expressive either, so the next question is whether you could group them using a different structure.
If the additional properties are optional or could be shared between multiple elements, you would need to write objects for them too, but the starting point is the same.
It is of course possible that you genuinely need a Map to link values to additional properties "because of reasons". In that case you can do something like this:
public class Container {
private double[][] values;
private Map<Double,AdditionalProperties> properties;
public double getValue(int x, int y) {
return values[x][y];
}
public AdditionalProperties getProperties(int x, int y) {
return properties.get( getValue(x, y ) );
}
}
This way you can hide the fact that you use two separate data structures to store the data, and maintain data integrity between them.
Note though that this is semantically very different from the first solution. In particular, positions containing the same value will share their AdditionalProperties.
(There are also practical problems with this implementation, #dasblinkenlight already pointed out why using doubles as keys to a map is an issue, the other is that an autoboxing conversion happens and that can add some memory and run time overhead. All these problems can be overcome with careful coding, but I'm only demonstrating the basic concept here.)
since the HashMap compares for references this works.
Comparing for references also happens to be the biggest problem with this approach: the fact that the object is a 2d array of double does not matter - one could simply replace your map with
HashMap<Object,ElemProperties> elemProperties;
without losing any functionality.
A better approach would be making a class that represents 2D keys based on arrays of double:
class KeyDouble2D {
private final double[][] key;
public KeyDouble2D(double[][] key) {
// Make a copy of key into this.key
}
public boolean equals(Object other) {
// Ensure that other is KeyDouble2D, then compare key
// sizes, and finally compare arrays element-by-element.
// Make sure to use `Double.equals` method to avoid NaN != NaN problem.
}
public int hashCode() {
// Compute hash code as a sum of hash codes in 2D array
}
}
You can use this class for keys of your hash map:
HashMap<KeyDouble2D,ElemProperties> elemProperties = ...;
...
ElemProperties prop = elemProperties.get(new KeyDouble2D(exampleArray)).getProp1();
Note that one needs to be very careful when using arrays of double for hash keys, for the same reason why one needs to be careful when comparing doubles for equality.
Why not create a class DoubleWithProperties, and manipulate an array of this class, instead of using a hashmap?
class DoubleWithProperties {
double value;
ElemProperties props;
public DoubleWithProperties(double value, ElemProperties props){
...
}
}
DoubleWithProperties[][] array = new DoubleWithProperties[5][5];

Change from String to Object Name Java

I have 3 ints named A, B, and C. These are to be multiplied with the number 52. I have a string that contains the name of which int I want to mulitply (in example below my string type == A;.
I want to know if there is anyway to make the name of the String change into the name of the object/int that I wish to use.
What I have right now:
public class MultiplySomeNumbers{
int A = 100;
int B = 200;
int C = 300;
String type = "A";
final int multiplied = 52;
public int multiply(String type){
return multiplied* ____ //What goes here?
}
}
I DON'T want to do anything like this:
public int multiply(String type){
if(type.equalsIgnoreCase("A"){
return multiplied*A;
}else if(type.equalsIgnoreCase("B"){
...
Any help would be greatly appreciated!
No, that is not possible (maybe with Reflection, but it's still a no-go). Every single situation where you think you might need this does not need it.
There are several issues, but here are a few:
No intellisense for those generated variables
Very unclear code
Ambiguous naming (what if you create a new variable that happens to have the same name as a generated one?)
etc etc etc
You will have to go with your second option.
We might be able to provide a different solution, but the question is rather unclear as it is right now. Perhaps you could expand a little so we can help you better.
Although there may be a way to do this with reflection, it's probably a really bad idea. If you really can't just pass in the value, but want to specify a limited set of constants by which you can multiply, I'd recommend creating an enumerated type.
Taking your same example, but using an enum instead of trying to look up constants by name, would look something like this:
public class MultiplySomeNumbers{
public enum Type {
A(100),
B(200),
C(300);
private final int value;
private Type(int value) {
this.value = value;
}
public final int getValue() {
return value;
}
}
Type type = Type.A;
final int multiplied = 52;
public int multiply(Type type){
return multiplied * type.getValue();
}
}
While there is nothing wrong with using an enum for this solution, it may not be the most flexible solution. Enums are, by design, effectively immutable ... they are intended to have the sense of constants. If you wish to change the value of a variable by multiplying its value by 52, then this is not possible with enums.
What I think you really should do is use a HashMap. A Map is a key / value pair.
The key is the "variable's name"; a String quantity
The value is the "variable's current value"; an Integer quantity (not int!)
Your Map can be declared like this:
Map<String, Integer> myVariables = new HashMap<String, Integer>();
then to load your variables into the map, you simply call the Map's put() method:
myVariables.put("A", Integer.valueOf(100));
myVariables.put("B", Integer.valueOf(200));
myVariables.put("C", Integer.valueOf(300));
Retrieving the value of a variable is as simple as using the get() method with your variable name as the key:
int val = myVariables.get("A").intValue();
Notice that I have chosen to box and unbox the primitive int values myself rather than rely on autoboxing. This is just a personal choice. It does trade off conciseness, but I'd rather see what's actually happening.
In my opinion, using reflection to determine a class field to access dynamically at run time is wholly unsatisfactory and should be avoided ... most especially since using the Java Collections API enables a statically typed, type safe solution that can be checked at compile time.
You can't check for a variable's name. For more information look here, there are some good answers:
Java Reflection: How to get the name of a variable?
But maybe a HashMap can help you, where you store "A", "B", "C" as keys and the respective numbers as value.
edit: Okay, maybe with something like this http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html it could be possible.

Using Java's contains(Object) method for Collections (eg HashSet) without actually having the object

I recognise that sounds a bit mad but to explain what I mean:
I have a Collection (eg HashSet) containing several quite slow initialisation objects and I want to see if the Collection already contains a particular object. Let's use Vector3d as an example (I know that is not expensive to initialise).
So the Collection contains:
Vector3d(1,1,1)
Vector3d(2,1,1)
Vector3d(3,1,1)
And I want to ask the Collection the question "does the Collection contain a Vector3d with x=2, y=1 and z=1 (i.e. I already know the data the .contains() method would hash against). So I could create a new Vector3d(2,1,1) and then use .contains() on that but as I said the objects initialisation is slow, or I could run through the entire Collection manually checking (which is what I'm doing now) but thats (as I understand it) slower than .contains() since it doesn't use hash. Is there a better way to do this?
The objects in question are mutable but the data that the equals method is based upon is not. (In my case they are blocks at x,y,z co-ordinates, the contents of the blocks may change but the x,y,z co-ordinates will not)
ArrayList is the correct data structure if you only need to iterate through all of your elements or access your elements by position. It is the wrong data structure for anything else.
What you are trying to do is answer the containment question quickly, which is what Sets and Maps are for. It would make much more sense to create a separate, cheaper Vector3dKey class with the simple hash function you want and insert your expensive objects into a Map< Vector3dKey, Vector3d > at the same time as, or instead of, an ArrayList< Vector3d >. Java obviously won't keep two copies of your expensive vectors, just copies of the references. Of course, this whole scheme breaks down if your Vectors are mutable.
Using the .contains() method on an ArrayList will result in the equals method being invoked against each and every instance in the ArrayList.
While that will work for you, it may not prove beneficial for extremely large ArrayLists. If performance is a problem, you may wish to hold a HashSet containing references to the Vector3d objects. Invoking contains on a HashSet (or any Set) is drastically faster.
If you REALLY have to use a list (and not a hash) you might as well iterate over the list, retrieve each object and check it's attributes manually--I mean that will be pretty much as quick as "Contains".
If you were going to use a hash instead of a list then you should use a different object for comparison. For instance, if you use a HashMap with your above example your keys could be the following strings:
"1,1,1","2,1,1","3,1,1"
This would make a lookup instant and easy. If the list could contain other types of objects, maybe "Vector3d(1,1,1)" would be a better string. It's easy to re-create without being expensive or adding code complexity.
If you were using a list because you needed to retain order, look at LinkedHashMap.
Also I suggest you create a function to derive the string from the object (when inserting) or from the parameters (when searching) rather than distributing the functionality around your code, this is the kind of thing you are likely to need to change or expand on later.
Code based on Judge Mental's answer
package mygame;
import java.util.HashMap;
import java.util.Map;
public class Main{
public Main(){
Map<CheapKey,ExpensiveClass> map=new HashMap< CheapKey, ExpensiveClass>();
for(int i=0;i<100;i++){
ExpensiveClass newExpensiveClass;
newExpensiveClass=new ExpensiveClass(i,0,0);
map.put(newExpensiveClass.getKey(), newExpensiveClass);
}
CheapKey testKey1=new CheapKey(1,0,0);
CheapKey testKey2=new CheapKey(1,0,1);
System.out.println(map.containsKey(testKey1)); //there is an object under key1
System.out.println(map.containsKey(testKey2)); //there isn't an object under key2
ExpensiveClass retrievedExpensiveClass=map.get(testKey1);
}
public static void main(String[] args) {
Main main=new Main();
}
protected class ExpensiveClass{
int x;
int y;
int z;
public ExpensiveClass(int x, int y, int z){
this.x=x;
this.y=y;
this.z=z;
for(int i=0;i<10000;i++){
//slow initilisation
}
}
public CheapKey getKey(){
return new CheapKey(x,y,z);
}
}
protected class CheapKey{
int x;
int y;
int z;
public CheapKey(int x, int y, int z){
this.x=x;
this.y=y;
this.z=z;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CheapKey other = (CheapKey) obj;
return true;
}
#Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + this.x;
hash = 79 * hash + this.y;
hash = 79 * hash + this.z;
return hash;
}
}
}
The contains method will invoke the .equals method of an object, so as long as the implementation of .equals for that class compares the values contains in the objects not their pointers then using contains will work.
http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#contains(java.lang.Object)
Edit misread your question a bit. I think it comes down to how big the list is vs how long the initialisation takes. If the list is short, iterate through it and manually check. However if the list is likely to be long, creating the objects and using .contains could well be more efficient.
ArrayList.contains doesn't use hashing; it's exactly the same speed as the manual check. It makes no difference either way.
Using a fake object class is doable, but almost certainly a code smell.

Purpose of return new?

public Double squareRoot(Double d)
{
return new Double (Math.sqrt(d.doubleValue()));
}
What is the purpose of "return new"? Would it still work if "new" was removed?
Yes, in fact you can remove even more code:
public Double squareRoot(Double d)
{
return Math.sqrt(d);
}
Even though Math.sqrt returns a double and not a Double. This is done by a java feature called Autoboxing.
But as #assylias pointed out, you asked if it is ok to just remove the new keyword. The answer to that is no. This does not compile:
public Double squareRoot(Double d)
{
return Double (Math.sqrt(d.doubleValue()));
}
The error is "Method call expected". You can't call a class' constructor as a method. You can only call a constructor by putting a new keyword in front of it.
You are not using something called 'return new', instead, the following code:
return new Double (Math.sqrt(d.doubleValue()));
actually does
new Double (Math.sqrt(d.doubleValue())) (which creates a new Double object with the value of Math.sqrt(d.doubleValue())
return value of step 1
Java also has a concept called autoboxing which allows for automatic conversion between objects of type Double and values of the type double. As result you don't need to explicitly create an object using new Double(...) because Math.sqrt(...) returns a value of double. Java will do that automagically for you. Same applies to the parameter d: you don't need to call doubleValue() on it.
So you can change the code to:
public Double squareRoot(Double d) {
return Math.sqrt(d);
}
Or better yet use the primitive double as an object of type Double is not really necessary here:
public double squareRoot(double d) {
return Math.sqrt(d);
}
Or better yet (as forivall pointed out in comments to another answer) don't bother with this method and simply call Math.sqrt(...) directly.
This new Double (Math.sqrt(d.doubleValue())); involves converting a primitive type double to its wrapper class Double, and the other way round. But it's unnecessary. Instead, you can do return Math.sqrt(d), which is an example of both autoboxing and unboxing.
"Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing."
http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Yes, it would still work (provided you also remove the brackets around Math.sqrt(d)) - as long as you're using Java 5 or newer. That feature is called autoboxing / auto-unboxing, meaning the JVM will automatically wrap a primitive in it's corresponding wrapper type.
However, the disadvantage of writing return new Double(Math.sqrt(d)) is that is slightly less efficient. If you use return Double.valueOf(Math.sqrt(d)) (or just return Math.sqrt(d); is that the first option will create a new Double object, whereas the latter two options will try to re-use an earlier created Double instance.
See the Double.valueOf() Javadoc for details.

Arrays of different types

Is it possible to have an array that contains two different types of data? I want to have an array that contains a double and also a string. I attempted:
ArrayList<double><String> array;
But that didn't work.
Sorry for the silly question, but it has been a while since I have used something like this.. Can you refresh my memory on how would I declare and populate such an array?
And then to take it a step further, I would like to sort the array by the double if possible?
Thanks!
Firstly, it's worth being clear about the difference between an array and an ArrayList - they're not the same thing at all.
However, in either case you can't do what you want. The closest you can probably come is declaring your own type. (EDIT: My original code had a double or a string... I've now changed it to be a double and a string. Let me know if this change isn't what you had in mind.)
public final class DoubleAndString
{
private final String stringValue;
private final double doubleValue;
public DoubleAndString(String stringValue, double doubleValue)
{
this.stringValue = stringValue;
this.doubleValue = doubleValue;
}
public String getString()
{
return stringValue;
}
public String getDouble()
{
return doubleValue;
}
}
Then create an ArrayList<DoubleAndString> or a DoubleAndString[].
Now, this feels somewhat vanilla at the moment - presumably the double and string values actually have a greater meaning - a name and a score, for example. If so, encapsulate that in a type which describes the pairing more appropriately.
As for ordering - you could make DoubleAndString implement Comparable<DoubleAndString> - but unless that's the only natural ordering which makes sense, I'd write a Comparator<DoubleAndString>:
public class DoubleComparator implements Comparator<DoubleAndString>
{
public int compare(DoubleAndString ds1, DoubleAndString ds2)
{
return Double.compare(ds1.getDouble(), ds2.getDouble());
}
}
Then you can use Collections.sort to sort an ArrayList<DoubleAndString> or Arrays.sort to sort an array.
You can use ArrayList<Object> and you can then use anything you'd like. Encapsulate the double in a Double object and when you retrieve the object use instanceof to check if it's really a double or a String.
I must say, it's unlikely this 'design' would win you any awards. Is it possible to rethink the solution you're considering for your problem, and see if you could do with a different kind of approach?
It sounds like you want a Map. Since you wish to sort the Map, a TreeMap may be optimal.
Map<Double, String> myMap = new TreeMap<Double, String>();
Maps are associative. Each double has an associated string. If you want multiple strings per double, you can use a
Map<Double, ArrayList<String>>
You might already know this, but it is not certainly not a good idea to store different types in a list. By definition an array is a collection of similar objects and stuffing all kinds in it makes things fuzzy. So really you would rather have a separate type to hold these different values.
Well, if you want to have an array with an arbitrary number of elements, then you simply need to use a type that is a common ancestor to both. In this case, that would be Object (since String and Double both inherit from Object). This will require you to check the types, though, when you retrieve or use them.
If you are using a fixed number of multiple different types, then what you really want is a "tuple". However, Java currently does not have an implementation of tuple available. For two items:
public class Pair<T1,T2>
{
public Pair(){
this(null,null);
}
public Pair(T1 x1){
this(x1,null);
}
public Pair(T1 x1, T2 x2){
_x1 = x1;
_x2 = x2;
}
public T1 getFirst(){
return _x1;
}
public T1 getSecond(){
return _x2;
}
private T1 _x1;
private T2 _x2;
}
You can just do ArrayList<object> arraylist and then you can put anything in it, but that may not be what you want.
Then, to sort you would just use your own comparator but, as theatrus mentioned, are these two values supposed to be connected, or do you have a single-dimension array with two different data types?
An ArrayList by definition only contains one object per position. You could do something like this:
List<MyTuple> list = new ArrayList<MyTuple>();
public static class MyTuple implements Comparable<MyTuple> {
private Double doubleValue;
private String stringValue;
//getters and setters
public int compareTo(MyTuple tuple) {
return doubleValue.compareTo(tuple.getDoubleValue());
}
}
You can then use the Collections.sort() method to sort it by the Doubles.
What do you want to do?
If it is not a key value mapping, you should create a new class for this.
You may want to look at the Number base class.
List<Number> list = new ArrayList<Number>();
list.add(new Integer(3));
list.add(new Double(5.2));
You may interpret the numbers as strings, using NumberFormat:
NumberFormat formatter = new DecimalFormat("#.##");
String s = formatter.format(list.get(0));
Though this may not be what you want, you are a bit short on details about your end goal.
if you are basically not trying to do any comparisons/sorting on the ArrayList then you could create something as below:
List list = new ArrayList();
otherwise.. Jon Skeet's answer was best approach.

Categories

Resources