I seem to have a bit of misunderstanding with Java Generics and I hope you can help me. I tried to create a map like so:
Map<Debater, int>
(Debater is an Interface I declared) but java complained about the int, so I did:
Map<Debater, Integer>
I suppose it's because int is not a class while Integer is, is this correct?
Also, Now I get a Debater and I need to add 1 to its value in the map. How do I do that?
Yes, you are correct.
As for incrementing:
map.put(debater, map.get(debater) + 1);
Autoboxing will take care of "switching" between the object and the primitive.
Note that this (as noted in the comments) will throw a NullPointerException if you don't have a value for this debater in the map already. So if you want to do 2-in-1, it can be reworked as follows:
map.put(debater, map.containsKey(debater) ? map.get(debater) + 1 : 1);
That's correct. A Map can only hold Objects.
Also, Now I get a Debater and I need to add 1 to it's its value in the map. How do I do that?
I suggest you to grab AtomicInteger for that so that it's more failsafe in case of multithreaded environments.
Map<Debater, AtomicInteger> map = new HashMap<Debater, AtomicInteger>();
// ...
map.get(debater).incrementAndGet();
Else you'll need to add more code to synchronize the update to avoid that threads get the "wrong" value.
I suppose it's because int is not a
class while Integer is, is this
correct?
Correct.
Also, Now I get a Debater and I need to add 1 to it's value in the map. How do I do that?
This should do the trick:
map.put(debater, map.get(debater)+1);
You're right, it's because you have to specify a class.
As for your question, you juste have to do :
myMap.put(myDebater, myMap.get(myDebater) + 1);
All conversions between int and Integer will be done by autoboxing.
You are correct about the int vs. Integer part.
To increment the value safely use:
Integer currentValue = map.get(debater);
if(currentvalue == null) {
map.put(debater, 1);
} else {
map.put(debater, currentValue + 1);
}
or you could use map.contains(debater) first if you want to handle the case that a debater is not contained in the map separately.
Java does not allow primitive types in generics. Fortunately, each of the primitive types has a "box" reference type, e.g. Integer for int, Boolean for boolean, etc. The language is aware of this association, and can do automatic boxing and unboxing for you. This means that you can do something like this:
Integer i = 5;
i++;
There are some caveats with automatic boxing/unboxing that you have to be aware of. The classic example is the following:
List<Integer> list = new ArrayList<Integer>();
list.add(3); // this is autoboxed, and calls list.add(E)
list.remove(3); // this invokes list.remove(int) overload !!!!
list.remove((Integer) 3) // this is how you call list.remove(E)
You will find that the above code as is will throw IndexOutOfBoundsException, because the first remove tries to remove the 3rd element, instead of the element 3.
You cannot use primitive type (such as int, float, char etc.) as a generic type - collections in Java are generic. That's why you have to use Integer instead of int.
Related
In java for a comparison in an if statement, I wrote
if (x == 1)
and got a comment in code review to use NumberUtils.INTEGER_ONE instead of 1. I was wondering what benefit does it actually add to the code.
NumberUtils.INTEGER_ONE comes probably from commons-lang.
In commons-lang, it is defined as :
public static final Integer INTEGER_ONE = new Integer(1);
In commons-lang3, it is defined as :
public static final Integer INTEGER_ONE = Integer.valueOf(1);
The first version doesn't use the internal integer cache (as didn't exist yet)
while the second version takes advantage of it.
Now, whatever the version you are using, it doesn't really matter for your question as you compare integer values and you don't assign or create integer value (case where the cache could make more sense).
Suppose you are using it in this way :
if (x == NumberUtils.INTEGER_ONE)
If x is a primitive, it is not very efficient as it will produce an unboxing operation to convert NumberUtils.INTEGER_ONE to a 1 int primitive.
If x is an object, it is not a good idea either as Integer objects should be compared with equals() or intValue().
1) When Java encounters int[], does it actually understand it as Integer[], I mean array can only hold references, not primitives ?
2) When it comes to return two immutable integers from a function, are those two ways equivalent?
int a, b;
...
int[] returnVal = {a, b};
return(returnVal);
vs.
Integer a, b;
...
Integer[] returnVal = {a, b};
return(returnVal);
3) What is the standard practice to return two immutable integers?
Edits:
I'm wondering if "immutable" is actually the correct term to use as my question is about how to return safely a pair of integer values to a caller and at the same time preventing the caller to change the original values without using unnecessary clone().
By trying different pieces of code, the short answer to point #2 seems to be that you can safely return the values as int[] or Integer[]. The caller may change the elements of the returned array, but not the initial values.
Answers below provide explanations for that, and valuable clues for points #1 and #3. As I cannot select multiple answers as correct, I've selected the most useful for me, but I thank everyone for their assistance.
No they are not identical. The compiler uses a trick called auto-boxing to make a and b switch between int and integers. It applies Integer.valueOf(primitiveInt) or integerInstance.intvalue() on demand and automatically.
The best semantics is whether any of the numbers can be absent. That only works for Integer, not int
There is a suitable Pair class in apache commons lang:
http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/tuple/Pair.html
Along with an immutable one.
Or create your own custom one:
Using Pairs or 2-tuples in Java
The standard practice is:
public class NameThatDescribesWhatAPairOfIntegersSymbolicallyRepresents {
private final int nameDescribingFirstInteger'sRole;
private final int nameDescribingSecondInteger'sRole;
public NameThatDescribesWhatAPairOfIntegersSymbolicallyRepresents(
int firstInteger, int secondInteger) {
nameDescribingFirstInteger'sRole = firstInteger;
nameDescribingSecondInteger'sRole = secondInteger;
}
public int getDescriptiveNameOfFirstInteger() {
return nameDescribingFirstInteger'sRole;
}
public int getDescriptiveNameOfSecondInteger() {
return nameDescribingSecondInteger'sRole;
}
}
Anything less will lead to a poor, disgruntled coder two years from now, staring at:
status = result[0] + 2 * result[1];
And proceeding to tear his hair out as he mouths to himself "What the !##$ is int[] result"?
=== Edit ===
Rant aside, the answers to your questions are:
1) No, these are totally different things. Primitives and Objects have different handles, consume different amounts of memory, and behave in different ways.
2) See (1) - no.
Additionally, no array - be it int[], or Integer[] - can ever be immutable. Java arrays are defined to be mutable always, you can't stop the caller from changing out the elements in an array. The only way to have a method return an "Immutable" array is if it generates a brand new copy every time it is called, and never hands out internal, mutable data.
3) See above
When Java encounters int[], does it actually understand it as
Integer[], I mean array can only hold references, not primitives ?
No for returning int[] collection of integer values(Primitive types) array is not same as Integer[] Collection of Integer Objects (Objects)
For Second Question.
No both are still not same because it's completely depend on return type of method.
As you can not return int[] where return type of method is Integer[].
For immutable return i want to add that you don't modified the object, rather you pointed the reference to a different object this happens only in Integer not in int.
In the sense of it depends on your code but if you ask which one is better i will say wrapping of int to Integer will be better in practice.
We come across these situations, in case we want to return wrapper class objects.
Simple solution for this would be to return map as follow:
private void parentFunction() {
Map<String,Integer> flagsForEventRule = new HashMap<>();
// call the method inside which you want to set these parameters
sample(flagsForEventRule);
System.out.println(flagsForEventRule.get("pathsMatched"));
}
private void sample(Map<String,Boolean> flagsForEventRule) {
// you can set the values in map like this
flagsForEventRule.put("pathsMatched", 1);
flagsForEventRule.put("shouldCreateRule", 2);
}
1) When Java encounters int[], does it actually understand it as
Integer[], I mean array can only hold references, not primitives ?
This is 2 different things,
int[] is a standard primitives array,
Integer[] is an array of Objects - meaning array of pointers to Integer Objects.
When it comes to return two immutable integers from a function, are
those two ways equivalent?
int is always mutable
Integer is immutable
So in this case if you want to work with immutable objects, you need to use Integer, but then again you can always change the pointer in your array, and that way you'll lose consistency.
What is the standard practice to return two immutable integers?
I would look at apache common ImmutablePair()
I have an array list of integers and would like to delete an Integer value from it. To clarify: Let's say I have a function that takes in an ArrayList of Integers, and specified Integer value. I need to return the list with (value+1) deleted from it.
boolean deleteFromList(ArrayList<Integer> list, Integer value)
Now, if I do this:
return list.remove(value+1)
compiler will complain because it will try to invoke the delete method that takes int parameter and deletes an object from specified location, not the actual object.
So what is a proper way to deal with this? Is it better to do:
list.remove((Integer)(value+1))
or
int v = value.intValue();
v++;
list.remove(new Integer(v));
? In the second case, can I be sure the right value will be deleted?
list.remove(value+1) will remove at given index.
You can use list.remove(Integer.valueOf(value+1)) to remove the Integer.
Integer.valueOf(v) is recommanded instead of new Integer(v) because it allows reuse of Integer instances for special values (see javadoc).
EDIT :
In term of boxing/unboxing, it is possible to completely eliminate the problem using libraries like trove4j which define an dynamic array of integer storing the primitive values instead of numeric class (see TIntArrayList). No boxing, no unboxing, lower GC use and better performance.
In the second case, can I be sure the right value will be deleted?
Yes you can.
The remove method will use equals(Object) to identify the object to be removed from the list. Since Integer.equals compares by value (not by object identity), it doesn't matter how you created the Integer instances ... provided the wrapped int values are the same.
However ... your second version is inferior to the first version:
It cumbersome: 3 statements instead of 1.
You are using new Integer(...) rather than Integer.valueOf(...) which is always going to create a new instance. By contrast, autoboxing (or calling Integer.valueOf(...) explicitly) makes use of the Integer classes instance cache, and that will often avoid creating a new instance.
list.remove(Integer.valueOf(value+1));
should work fine.
Do you looking for this one.
Collections.sort(list);
int index = list.indexOf(5);
list = list.subList(0, index-1);
System.out.println(list);
You can use list.indexOf(value + 1) since that method only takes the object. Then use that index to remove the element.
int i = list.indexOf(value + 1);
list.remove(i);
If you need to remove all instances of value + 1 then continue until i is -1 (not found).
Or, just iterate over it and remove as you find them
for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); ) {
Integer integer = iterator.next();
if (integer == value + 1) {
iterator.remove();
}
}
A more effective way might be to use a TIntArrayList from Trove4j library which wraps int[] array and doesn't use wrapper types. For this reason it takes 3x times less memory and is much faster.
What is the reason why Wrapper classes (like Integer, Double, etc.) don't have a setter for their inner primitive value ?
I am asking this because that kind of functionality would have simplified calculus, and have made the Java language a little more flexible .
Let me give you some examples.
1) Let's take the following example:
Integer x = new Integer(5);
x++;
The previous code behind the scenes is performing autoboxing . Something like:
int x_tmp = x.intValue();
x_tmp++;
x = new Integer(x_tmp); // Yes that's a new memory allocation
Because of this problem doing calculus on Wrapper is slower than performing on plain primitive types. With a setter it would've been more easy to increment the inner value, without allocating another object on the heap.
2) Another issue that is bugging me is that is impossible in Java to write a swap function like I can do in C (using pointers) or in C++ (pointers or references).
If i write void swap(Integer x, Integer y) I cannot acces the inner value because, and It is going to be impossible for me to swap the values.
PS:
A friend of mine suggested that i should consider the bigger picture, and think in terms of concurrency and type immutability.
So do you have an explanation for this ?
Thanks!
Wrapper classes are usually not used unless you need to put them into a collection. If they were mutable it would make problems if used inside sets and as keys for hashtables.
Sets and hashtables need the hash value to be always the same.
1) With a setter, the wrapper types would be mutable. Immutability is a good thing in many ways... threading, general understandability of the code etc. Personally I think it's a shame that Calendar and Date are mutable, for example.
In fact, your expansion of x++; isn't quite right - it uses Integer.valueOf which doesn't always create a new value. For example:
Integer x = 5;
x++;
Integer y = 5;
y++;
// This prints true
System.out.println(x == y); // Compare references
Only a limited range of Integer values are cached like this (the spec defines what values must behave this way, but allows for a wider range if the JRE wishes to do so)... but it does mean that it won't always be creating a new object.
2) Yes, Java doesn't have pass by reference. Frankly I very rarely find that to be a problem. How often do you really need to swap the values of variables?
Caching Integers in the range from -128 to 127 requires immutable Integers. Consider the follwoing code:
Integer id = Integer.valueOf(1); // a new Integer, cached in Integer class
// and somewhere else
Integer key = Integer.valueOf(1); // returns the cached value
Now if Integer was mutable and had a setter and someone did
key.setValue(2); // not legal Java code, just for demonstration
this would change the value of id too and, to a lot of peoples surprise:
Integer one = Integer.valueOf(1);
if (one != 1)
System.out.println("Surprise! I know, you expected `1`, but ...");
In Java, Strings and wrapper classes are designed as immutable to avoid accidental changes to the data. You can check the below article for further information.
Why Strings and Wrapper classes are immutable in java?
In which case should you use primitive types(int) or reference types (Integer)?
This question sparked my curiosity.
In which case should you use primitive
types(int) or reference types
(Integer)?
As a rule of thumb, I will use a primitive (such as int) unless I have to use a class that wraps a primitive.
One of the cases were one must use a wrapper class such as Integer is in the case of using generics, as Java does not support the use of primitive types as type parameters:
List<int> intList = new ArrayList<int>(); // Not allowed.
List<Integer> integerList = new ArrayList<Integer>(); // Allowed.
And, in many cases, I will take advantage of autoboxing and unboxing, so I don't have to explicitly perform conversions from primitives to its wrapper class and vice versa:
// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3);
int sum = 0;
// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
sum += number;
}
Also, as an additional note, when converting from primitives to its wrapper class objects, and unique instances of objects are not necessary, use the valueOf method provided by the wrapper method, as it performs caching and return the same instance for a certain value, reducing the number of objects which are created:
Integer i1 = Integer.valueOf(1); // Prefer this.
Integer i2 = new Integer(1); // Avoid if not necessary.
For more information on the valueOf methods, the API specification for the Integer.valueOf method can serve as a reference for how those methods will behave in the wrapper classes for primitives.
That really depends on the context. First prefer the primitive, because it's more intuitive and has less overhead. If it is not possible for generics/autoboxing reasons, or if you want it to be nullable, then go for the wrapper type (complex type as you call it).
The general rules I follow when creating an API can be summarized as follows:
If the method must return an value, use a primitive type
If the method may not always apply (eg: getRadioId(...) on an object where such an ID may not exist), then return an Integer and specify in the JavaDocs that the method will return null in some cases.
On #2, look out for NPEs when autoboxing. If you have a method defined as:
public Integer getValue();
And then call it as follows:
int myValue = getValue();
In the case where getValue() returns null you'll get an NPE without an obvious cause.
Since Java does something called auto-boxing and auto-unboxing, you should use the primitive type int in most cases because of less overhead.
The only time you absolutely need to use Integer is in generics.
List<int> list; // won't compile
List<Integer> list; // correct
One case in which Integer might be prefered is when you are working with a database where numerical entries are allowed to be null, since you wouldn't be able to represent a null value with an int.
But of course if you're doing straight math, then int would be better as others have mentioned due to intuitiveness and less overhead.
My rule of thumb is: use boxed primitives only when it's necessary to get the code to compile. The only places in your code where the names of the primitive wrapper classes should appear is in generic type parameters and static method calls:
List<Integer> intList = new ArrayList<Integer>();
int n = Integer.parseInt("123");
That's the advice I would give to new Java programmers. As they learn more, they'll run into situations where they have to be more discerning, like when dealing with Maps or databases, but by then they should also have a better understanding of the difference between primitives and boxed primitives.
Autoboxing tempts us to believe int and Integer (for example) are interchangeable, but it's a trap. If you mix the two kinds of value indiscriminately, you can end up comparing two Integer values with == or trying to unbox a null without realizing it. The resulting bugs can be intermittent and difficult to track down.
It doesn't help that comparing boxed primitives with == sometimes works as if it were doing a value comparison. It's an illusion caused by the fact that values within a certain range are automatically cached in the process of autoboxing. It's the same problem we've always had with String values: comparing them with == sometimes "works" because you're actually comparing two references to the same, cached object.
When dealing with strings we can just tell the n00bs never to compare them with ==, as we've been doing all along. But comparing primitives with == is perfectly valid; the trick (thanks to autoboxing) is being sure the values really are primitives. The compiler will now let us declare a variable as an Integer and use it as if it were an int; that means we have to exercise a greater level of discipline and treat it as an error when someone does so without good reason.
Rather than calling them "complex types", you'd be best served thinking Integer, Double, etc. as "Classes", and int, double, etc. as "primitives".
If you're doing any type of sophisticated math, the Class-based numeric representation like Integer and Double will be cumbersome and slow you down - many math operations can only be done with primitives.
On the other hand, if you're trying to put your numbers into collections like Lists and Maps, those collections can only contain objects - and thus you must use (or convert to) classes like Integer and Double.
Personally, I use primitives whenever I can get away with it, and only convert to the Class representations like Integer when it's time to do input or output, and the transport requires those representations.
However, if you aren't doing any math at all, and instead are just passing the values straight through your code, you might save yourself some trouble by dealing with the Class-based forms (like Integer) exclusively.
I think this is a bit late but I wanted to add my opinion just in case.
in some scenarios, it's required to use the wrappers as the lack of a value is different from the default value.
example,
for one project I worked on, there was a field on screen where the user could enter a double value, the business requirement clearly mentioned that if the user enters a 0 the meaning is different from not entering a value and leaving the field blank and this difference will make an impact later on in a different module.
so in this scenario we had to use the Double object, since I cannot represent a lack of value using the primitive; since the primitive will default to 0 which was a valid input for the field.
I dont think there is any rule as such. I would choose the types over primitives (Integer over int) when I write method signatures, Maps, collections, Data Objects that get passed around. As such I would still like to use Integer instead of int even inside of methods etc. But if you think that is too much trouble (to type extra "eger") then it is okay to use ints for local variables.
If you want to setAttribute to session you have to use Object like Integer,Boolean,String in servlets. If you want to use value you can use primitive types. Objects may be null but primitives not. And if you want to compare types for primitives use == but objects use .equals because in object comparision == looks not values it looks if these are the same objects. And using primitives makes faster the code.
When we deal with Spring getRequest mapping methods, using boolean value does not work.
For instance :
#GetMapping("/goal")
public boolean isValidGoal() {
boolean isValid = true;
return isValid;
}
Always opt for Boolean in those cases.