Generic pair with one known class? - java

I'm implementing a weighted probability algorithm, so I created a generic Pair class. Since the probability is calculated using numbers, the value of Pair would always be an Integer, but I wanted it to work the way where the key could be any Object. This is what I got:
class Pair<K, Integer> {
public K k;
public java.lang.Integer v;
public Pair(K k, java.lang.Integer v) {
this.k = k;
this.v = v;
}
// getters and other stuff
}
It works fine, but I find it weird that no matter what I type instead of the Integer part in the first line, it works the same. Am I missing something? Is there a better way to do that?

class Pair<K, Integer>
is equivalent to
class Pair<K, V>
where the name of the second generic parameter would happen to be Integer instead of V (and thus hiding the type java.lang.Integer, which forces you to use java.lang.Integer instead of just Integer in the code, to avoid a conflict).
Your class should only have one generic parameter:
class Pair<K>

You use generics when you may accept any type.
But since you know that type to be Integer, you do not need to make it generic.
The new version with one generic type argument will look like this:
public class Pair<T> {
public T t;
public int v;
public Pair(T t, int v) {
this.t = t;
this.v = v;
}
// ...
}
It is good practice, when you have just one generic type argument, to name it with the "T" letter.
Also, you can now use int instead of Integer.

The way you use it, Integer is just a type variable, same as K.
If you don't need the type of the second value of the pair to be a parameter, then don't declare it as type parameter, but just use Integer in the code:
class IntPair<K> {
private K first;
private Integer second;
public Integer someIntegerSpecificFunction() {
// do stuff to internalPair.second
}
K getFirst() {
return first;
}
Integer getSecond() {
return second;
}
}

Related

Java generic T extends Object

Given the following class:
public class TestMap<K,V> {
private HashMap<K,V> map;
public void put(K k, V v) {
map.put(k, v);
}
public V get(K k) {
return map.get(k);
}
}
and this function:
static<T extends Object> String getObj(TestMap<T, String> m, String e) {
return m.get(e);
}
Why does "get" show this error:
The method get(T) in the type MyHashMap<T,String> is not applicable for the arguments (String)
When getObj states T extends Object, and the map has been initialized with TestMap<T, String> m, why can't String be used as parameter? I cant wrap my head around why this doesnt work, as String is a subtype of Object ?
I tried extending T from a custom superclass and using a subclass instead of String.
get() requires as an argument a key, which is of type T, not String.
So either you need to change e to type T or change the type of the Map, e.g., to TestMap<String, T>.
Generics describe what an Object is, List<String> strings is a list of Strings. That gives us some convenience, we don't have to cast. String s = strings.get(0); and we get some compile-time protection. Integer i = 1; then strings.add(i); fails to compile.
The error you are getting is a compile time protection. The key you're providing is an Object, so it might be the correct type. In the case of a map, "why not check?" It is just going to hashcode and check for equality which is ok. In the case of a List though, strings.add((Object)i); needs to fail.
If the doesn't fail, then later something might call. for(String s: strings) and get a class cast exception.
To fix this you can change you V get(K k) method to a V get(Object k) the same as map uses. Your get method requires type K a map normally has a get method with a Object
As mentioned "T extends Object" is the same as just "T". You use the extends when you want to put a lower bound on something. public <T extends Number> int sum(List<T> numbers). In this case "T" can be any class that extends numbers. We can do Number n = numbers.get(0); because we know it is at least a number. But we could not do numbers.add(n); because while T is at least a number, it could be something else like an Integer, Double, Number, BigDecimal etc.

How is this generic array legal?

The problem of generic arrays (i.e., the impossibility of them) seems to be a recurring theme for me. Below is the relevant code of a HashMap data structure. Obviously, I cannot declare a Bucket[], since generic arrays are impossible. However, I can declare a MapThing.Bucket[]. Am I correct when I assert that this is good practice, since even though MapThing.Bucket[] is a raw type declaration, the actual MapThing.Bucket[] instance is type parameterized by its enclosing instance?
Thanks for any insight!!!
Chris
public class MapThing<K, V> {
private Bucket buckets[];
public static void main(String[] argv) {
MapThing<String, Integer> thing = new MapThing<>();
thing.put("got your number", 8675309);
}
#SuppressWarnings("unchecked")
public MapThing() {
buckets = new MapThing.Bucket[314159];
}
public void put(K key, V value) {
Bucket bucket = new Bucket(key, value);
// Prints typeof bucket key: String, value: Integer
System.out.println("typeof bucket key: "
+ bucket.getKey().getClass().getSimpleName() + ", value: "
+ bucket.getValue().getClass().getSimpleName());
buckets[Math.abs(key.hashCode() % buckets.length)] = bucket;
}
private class Bucket {
private K key;
private V value;
Bucket(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
}
Obviously, I cannot declare a Bucket[], since generic arrays are
impossible.
You can ALWAYS declare a variable of any array type. Always. It is perfectly fine to declare variables of Bucket[] or ArrayList<String>[] or whatever.
You cannot use the array creation expression (i.e. new X[...]) with a parameterized type (i.e. if X is Something<SomethingElse> where SomethingElse is anything except ?). You can use array creation expression with a raw type (i.e. new X[...] where X is a raw type), e.g. new ArrayList[10].
Therefore, if Bucket were a raw type, then new Bucket[10] would be perfectly fine. The thing is, Bucket is not a raw type. Bucket is a non-static inner class inside a generic outer class. That means it is within the scope of the type parameters of its outer class. In other words, if you write the unqualified type Bucket inside MapThing, it implicitly means MapThing<K,V>.Bucket, which is a parameterized type.
To get the raw type, you need to explicitly qualify it with the outer class, as in MapThing.Bucket. So new MapThing.Bucket[10] will work.
Alternately, if you don't want to use raw types, you can parameterize it with all wildcards: new MapThing<?,?>.Bucket[10].

Sequence number of an enumeration litteral in Java

Given the following definitions:
public enum SampleEnum1 { Uno, Dos, Tres }
public enum SampleEnum2 { One, Two, Three, Four }
I need two methods doing this:
Given the integer 2, return Dos if applied to SampleEnum1, Two if applied to SampleEnum2
Given the value One, return 1
In fact I need to translate an enumeration litteral into its sequence number in the enumeration definition, and vicae versa.
I don't mind using generics, reflexion, or whatever, as long as the same 2 methods work for any enumeration.
Do you have the solution?
Another approach is to use a helper method like
public static <E etxends Enum<E>> E lookup(Class<E> eClass, int number) {
return eClass.getEnumConstants()[number-1];
}
SampleEnum1 se1 = lookup(SampleEnum1.class, 2);
BTW: You could start with Zero which would simplify your code as well.
If you can be sure to keep your enums in order in the source file, you can do like this to get the enum by number:
public static SampleEnum1 getSpanishEnum(int index) {
return SampleEnum1.values()[index - 1];
}
public static SampleEnum2 getEnglishEnum(int index) {
return SampleEnum2.values()[index - 1];
}
And to go the other way, you can do a loop
public static <E extends Enum> getEnumIndex(E value, E[] values) {
for(int i = 0; i < values.length; i++) {
if(value == values[i]) {
return i + 1;
}
}
throw new NoSuchElementException();
}
calling it like this:
getEnumIndex(SampleEnum1.Dos, SampleEnum1.values());
The forward direction can be done using the Class.getEnumConstants() method:
public static <E extends Enum<E>> E getValue(Class<E> eClass, int index) {
return eClass.getEnumConstants()[index - 1];
}
Called as follows:
SampleEnum2 two = getValue(SampleEnum2.class, 2);
(Unfortunately, we can't write a generic method that uses the values() method that every enum has. It is static so we can't access it by polymorphic dispatching. To access it reflectively we'd need to know the actual class of E ... and that requires a Class<E> object. And if you have to pass that, you may as well call its getEnumConstants method.)
The reverse direction is simpler:
public static <E extends Enum<E>> int getIndex(E e) {
return e.ordinal() + 1;
}
Of course, it is much neater if you follow the normal IT convention that the indexes of a collection start from zero.

Dynamic casting in Java

Before I get chided for not doing my homework, I've been unable to find any clues on the multitude of questions on Java generics and dynamic casting.
The type Scalar is defined as follows:
public class Scalar <T extends Number> {
public final String name;
T value;
...
public T getValue() {
return value;
}
public void setValue(T val) {
this.value = val;
}
}
I would like to have a method that looks like this:
public void evilSetter(V val) {
this.value = (T) val;
}
Sure, this is generally discouraged. The reason I want such a method is because I have a collection of Scalars whose values I'd like to change later. However, once they go in the collection, their generic type parameters are no longer accessible. So even if I want make an assignment that's perfectly valid at runtime, there's no way of knowing that it'll be valid at compile time, with or without generics.
Map<String, Scalar<? extends Number>> scalars = ...;
Scalar<? extends Number> scalar = scalars.get("someId");
// None of this can work
scalar.value = ...
scalar.setValue(...)
So how do I implement a checked cast and set method?
public <V extends Number> void castAndSet(V val) {
// One possibility
if (this.value.getClass().isAssignableFrom(val.getClass()) {
// Some cast code here
}
// Another
if (this.value.getClass().isInstanceOf(val) {
// Some cast code here
}
// What should the cast line be?
// It can't be:
this.value = this.value.getClass().cast(val);
// Because this.value.getClass() is of type Class<?>, not Class<T>
}
So I'm left with using
this.value = (T) val;
and catching a ClassCastException?
You have:
this.value.getClass().isAssignableFrom(val.getClass())
This is probably going to be a problem unless you can be certain value will never be null.
You also have:
this.value = (T) val;
This will only cast to Number and not to T because under the hood T is just a Number due to type-erasure. Therefore if value is a Double and val is an Integer, no exception will be thrown.
If you actually want to perform a checked cast, you must have the correct Class<T> object. This means you should be passing Class<T> in the constructor of your object. (Unless you can be sure value is never null, in which case you can go with your first idea.) Once you have that object (stored in a field), you can perform the checked cast:
T value = valueClass.cast(val);

Java Generics and Infinity (Comparable)

With the type Integer you can do this:
int lowest = Integer.MIN_VALUE;
What can I do if I use generics?
K lowest = <...>;
I need this in order to implement something similar to a PriorityQueue.
I have access to a node I want to remove from the queue, but it is not the min.
1. I need to make it the min by decreasing the key of that node,
2. And then remove the min.
I am stuck on the first step. The only thing I can do is set the key of the node to the current min. Not sure it is enough.
There is no generic form of MIN_VALUE or MAX_VALUE for all Comparable types.
Think about a Time class that implements comparable. There is no MAX_VALUE for Time even though it is Comparable.
I am trying to imagine what scenario would require such behavior. This is the best I can come up with...
WARNING: This code is dangerous. Please be merciful to me for posting such an abomination. It is only a proof of concept.
public class Lowest<K> implements Comparable<K> {
public int compareTo(K other) {
return -1;
}
}
And then...
public class Test {
public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception {
K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!!
K maximum = lowest;
for (K value : values) {
if (maximum.compareTo(value) < 0) {
maximum = value;
}
}
if (maximum == lowest) {
throw new Exception("Could not find a maximum value");
} else {
return maximum;
}
}
}
This doesn't make any sense...
Given that you don't know what K is at that point, (i.e. You're implementing it generically... duh!) you can't specify a min/max bound for it.
in a case where K could be a int, long, string OR object, you couldn't sensibly guess to use
Integer.MIN_VALUE, "" OR NULL.
I guess what you're looking for is a K.MIN_VALUE_OF_EVENTUAL_TYPE but that doesn't exist.
You can make a wrapper class that "adds" a minimum and maximum value to all types. It just has two static instances that represent minimum and maximum, and then other instances wrap some other value of some type. When we do a comparison, we check if one of the things is the minimum or maximum, and return the proper result; and otherwise we just do the same comparison as the underlying type. Something like this:
class Extended<T extends Comparable<? super T>> implements Comparable<Extended<T>> {
private Extended() { }
private static Extended min = new Extended();
private static Extended max = new Extended();
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMin() {
return (Extended<T>)min;
}
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMax() {
return (Extended<T>)max;
}
public T value;
public Extended(T x) { value = x; }
public int compareTo(Extended<T> other) {
if (this == other) return 0;
else if (this == min || other == max) return -1;
else if (this == max || other == min) return 1;
else return this.value.compareTo(other.value);
}
}
Consider not making K a generic, but using an interface that wraps the primitive wrapper (a double wrapper!).
import java.util.HashMap;
public class NodeWrapper<K extends Comparable<K>> implements Comparable<NodeWrapper<K>> {
private static HashMap<Class, NodeWrapper> minVals = new HashMap<Class, NodeWrapper>();
private K value;
private NodeWrapper() {
super();
}
public NodeWrapper(K value, Class<K> clazz) {
super();
this.value = value;
if (minVals.get(clazz)==null) {
minVals.put(clazz, new NodeWrapper<K>());
}
}
public K getValue() {
return value;
}
public static NodeWrapper getMinValue(Class clazz){
return minVals.get(clazz);
}
public void setValue(K value) {
this.value = value;
}
#Override
public int compareTo(NodeWrapper<K> o) {
NodeWrapper min = minVals.get(this.getClass());
if (this==min && o==min) {
return 0;
} else if (this==min){
return -1;
} else if (o==min){
return 1;
} else {
return this.value.compareTo(o.value);
}
}
}
Briefly, the idea is that whenever a new class is instantiated, a minimum value is created and put into a static hashmap that stores the minimum values for each class. (In fact, these values are NOTHING at all, just a sentinel object, but since we will use object equality to determine if something is the min value, this is no problem at all.) All that's necessary is that the wrapped object be comparable to other instances of itself in general.
One drawback is that when you call getMinValue you will have compiler warnings, since the return type will have no generic information. There may be a more elegant way around this, but I can't think of it right now.
This general idea might be rather nice overall. However, I should really stress: this will absolutely break if you try it with any polymorphism or any mixing of mutually comparable classes. Longs and Integers in the same tree will completely destroy you.
er... what's the problem again?
PriorityQueue, like all Collections, allows you to use an instance of an object to remove it from the collection.
Uh doesn't this depend on what type K is?
The point of Generics is that K can be any type (or any subclass of a certain type); in order to be able to call methods on K or access properties of it, you need to restrict it's type bounds with wildcards.
just because an object is a comparable does not mean it has to have a minimum value. The reason int has a min value of -(2^(31)) is because you need 1 bit for a sign, so 2^31 is the largest (or smallest) possible integer that can be stored. For things like string, it does not make any sense since there is no largest/smallest possible string, it is memory bound.
You might have to create an interface "IInfinity", and have K extends IInfinity, and IInfinity to have a method "getInfinityValue()", and then wrap/extend Integer, Double, BigDecimal, etc in a class that implements IInfinity ... and ugh!
Basically you want any type K to implement some static functions say lowest and highest which obey the standard mathematical properties.
I assume that for this sense of lowest (or highest) to be usable you would want any Comparable object to have these methods. (or static fields). If you are only interested in your own custom objects, the way to do this would be to have everything inherit from an abstract data type which declared static fields for MINVALUE and MAX_VALUE and then your type varaibles would be . If you need this functionality for other classes you will need to cre4ate some sort of external hashmap which tracks these properties for different classes (but that would get pretty ugly)

Categories