I am trying to implement an algorithm that needs to compare some elements based on an ordering defined by an (any given) enum type, so I am trying to specialize it using enums in template definition. I tried with simple code to see if my idea would work, but I couldn't make it compile. Any ideas on how to approach the problem. Here is my code:
public class Algorithm <T extends Enum<T> >{
public TLCAlgorithm(){
T t1;
T t2;
if (t1<t2){
//do something
}
}
Essentially t1 and t2 will be different values of that enum type defined somewhere else. I am planning to have different enum types defining different kinds of orderings, so that by instantiating the class with a different enum type, the algorithm should behave differently. I would be instantiating as this: Algorithm<Ordering1> alg1=new Algorithm<Ordering1>().
Since you're calling this a "template", I'm guessing that you're coming from a C++ background. You should be aware that Java generics work very differently from C++ templates, despite the similar syntax: a generic method can't be specialized for different types like a function template can. The same compiled bytecode is used for all types of data.
The usual way to provide a customized ordering for a type in Java is by implementing the Comparator interface. To provide several orderings for a class Foo, for example, you'd write several classes that all implement Comparator<Foo> and define the compare(Foo, Foo) method differently in each one. Your algorithm can take an argument of type Comparator<Foo>, and the caller can pass an instance of one of those implementations.
You can also implement Comparator in an enum and implement compare separately for each enumeration value:
public enum Ordering implements Comparator<Person> {
BY_NAME {
#Override
public int compare(Person a, Person b) {
// Compare people's names...
}
},
BY_AGE {
#Override
public int compare(Person a, Person b) {
// Compare people's ages...
}
}
}
public class Example {
public void algorithm(Comparator<Person> comparator) {
Person a = // ...
Person b = // ...
if (comparator.compare(a, b) > 0) {
// ...
}
}
public void caller() {
algorithm(Ordering.BY_NAME); // Run algorithm using name ordering
algorithm(Ordering.BY_AGE); // Run algorithm using age ordering
}
}
Please change the proper Constructor name.
public Algorithm()
Use the ordinal method. It will give the order no of enum.
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as java.util.EnumSet and java.util.EnumMap.
if (t1.ordinal()<t2.ordinal()){
Use Condition like that.
Related
While working on a project, I came across the following code segment which appears to provide code, entirely contained inside a new variable declaration, which appears to override a method. I've, come across code of this form before but admittedly, I do not fully understand it. If anyone could explain the programming mechanisms upon which this code is based, I'd be very truly grateful. Particularly, when are overridden methods of this sort permitted inside of variable declarations. What other sorts of data structures allow such behavior? When is it advantageous to write code of such nature? Why not override the method outside of a variable declaration?
tempRequests.sort(new Comparator<Integer>()
{
#Override
public int compare(Integer integer1, Integer integer2)
{
return integer1.compareTo(integer2);
}
});
What other sorts of data structures allow such behavior?
-> You can sort objects by implements interface Comparable.
For example:
public class Car implements Comparable<Car> {
private String name;
#Override
public int compareTo(Car b) {
return name.compareTo(b.name);
}
}
->You can also use Comparator without override method compare inside the inner class.
public class Car implements Comparator<Car> {
private String name;
private double price;
#Override
public int compare(Car b1, Car b2) {
return b1.price - b2.price;
}
}
When is it advantageous to write code of such nature? Why not override the method outside of a variable declaration?
-> Image that after use sort object Car by name, you want to sort by something else (like by price, by weight).How to do this when you want to sort objects in different ways at different times? We use Comparator with define inside the inner class to do this.
*Additionally, Comparator is a functional interface since an only abstract method to implement. You can rewrite using a funky syntax in one line of code:
Ex:
Compareator<Car> byPrice = (b1,b2) -> b1.price - b2.price;
This mechanism has been explained well in the comments.
As an aside: ever since Java 8, this usage of anonymous classes is considered somewhat old fashioned, as it can be replaced with a simple Lambda expression:
tempRequests.sort((l, r) -> l.compareTo(r));
This applies to all "Functional Interfaces", which is defined as an interface with exactly one non-static and non-default method.
I've seen a number of similar questions, but I don't think any were quite isomorphic, and none quite answered my question.
Suppose there are two interfaces, Tree and Named. Suppose further that I am given a method whose signature is
public <T extends Tree & Named> T getNamedTree();
How can I save the returned value to a variable, while still retaining the information that it implements both Tree and Named? I can't find a way of declaring a variable like
public <T extends Tree & Named> T mNamedTree;
and trying to cast it to an interface extending Tree and Named results in a class cast exception.
Assuming there is no third interface inheriting both Named and Tree, you cannot retain information about both interfaces statically. The compiler will require you to do a cast for one or the other, or for both:
Object namedTree = getNamedTree();
Tree asTree = (Tree)namedTree;
Named asNamed = (Named)namedTree;
Both casts should succeed.
If you have influence on the design of the API for the class, ask the authors to introduce an interface combining both Named and Tree, and returning an instance of that interface instead.
One possible solution would be to create another interface that extends both Tree and Named, and simply store that as the variable:
interface NamedTree extends Tree, Named {
}
public NamedTree namedTree;
public NamedTree getNamedTree();
What scope does the variable has to have?
There is three possibilities here.
A) the variable is just a local variable. In that case you nearly have already the answer... you just need to declare a type-parameter for the enclosing method for that type:
interface ItfA { Number propA(); };
interface ItfB { Number propB(); };
class Main {
private <T extends ItfA & ItfB> T getT() {
return null;
}
private <TT extends ItfA & ItfB> void doStuffWithT() {
TT theT = getT();
System.err.println(theT.propA());
System.err.println(theT.propB());
}
}
B) The scope is the live of an object and in that case is a member field.
The obvious answer is to make the class generic and the type-parameter would
have the same & constraint:
interface ItfA { Number propA(); };
interface ItfB { Number propB(); };
class Main<T extends ItfA & ItfB> {
T theT;
public void setT(T newT) {
theT = newT;
}
public void doStuffWithT() {
System.err.println(theT.propA());
System.err.println(theT.propB());
}
}
C) The scope is the live of the program, then the variable is a static class member. Here you don't have a generics solution.
C.1) Obviously if the class of the values that you are going to handle is known you would just use that class as the field type.
C.2) If not, you could constraint the code to handle only classes that implement an interface that extends ItfA and ItfB. That interface, say ItfAB. Would be to field type.
C.3) Now, what about not imposing that constraint? What about allow the code to handle objects from any class that implement those interfaces?
Unfortunately there is no a clean-cut solution to that:
C.3.a) You could either type the field Object and provide methods to access it as an ItfA or as a ItfB (basically hiding the casting).
C.3.b) Or, instead of holding directly a reference to the object, you use a proxy object that implements those interfaces and delegates calls to those interfaces methods to the original "T" typed value. The class for that proxy could itself be a generic accepting an arbitrary <T extends ItfA & ItfB> value (similar to the B. example above).
I'd be extremely grateful if anyone could point out what I'm doing wrong.
I have an interface IDoubleSource, which I implement in a Person class. There is a LinearRegression class with a method that takes an IDoubleSource argument, but I will pass in the Person class.
As part of the IDoubleSource interface, an enum called Variables and a method called getDoubleValue(Enum) must be defined. Below, I show how I have done this in Person, and that the enum types are used to specify switch cases in the getDoubleValue() method.
The problems:
1) In LinearRegression, there is a method computeScore((MultiKeyCoefficient)Map, IDoubleSource), where the last argument is an interface. I cannot seem to access the Variables enum of the instance of the implementation of IDoubleSource within the computeScore method, despite having the interface imported into the LinearRegression class. It just doesn't register that an IDoubleSource has an enum called Variables (though I can call the getDoubleValue() method fine). Is there anything I'm obviously doing wrong, that prevents me accessing the enum Variables?
2) The getDoubleValue(Enum) method in Person class is designed to return a double value that depends on the value of the enum Variable passed to it. By looping through the keys (which are of String type) of a (MultiKeyCoefficient)Map in the LinearRegression class, I would like to use the keys to specify the enum values that I want as an argument to getDoubleValue(Enum) in the LinearRegression class (I would like getDoubleValue() to return several different values based on the Enum values it receives in the loop). However, I cannot use the (String) key in place of the expected enum as I get a ClassCastException java.lang.String cannot be cast to java.lang.Enum. How can I use the keys of the map to specify the Enums?
I'm not very familiar with using Enum types in Java, which may be a large part of my problem.
Now the code details:
I implement the following interface:
IDOUBLESOURCE INTERFACE
public interface IDoubleSource {
public enum Variables {
Default;
}
/**
* Return the double value corresponding to the given variableID
* #param variableID A unique identifier for a variable.
* #return The current double value of the required variable.
*/
public double getDoubleValue(Enum<?> variableID);
}
by creating the class:
PERSON CLASS
public class Person implements IDoubleSource {
public enum Variables {
nChildren,
durationInCouple,
ageDiff;
}
public Person() {
...
}
public double getDoubleValue(Enum<?> variableID) {
switch ((Variables) variableID) {
case nChildren:
return getNChildren();
case durationInCouple:
return (double)getDurationInCouple();
case ageDiff:
return getAgeDiff();
default:
throw new IllegalArgumentException("Unsupported variable");
}
In another package, I have a Class:
LINEARREGRESSION CLASS
public class LinearRegression
private MultiKeyCoefficientMap map = null;
public LinearRegression(MultiKeyCoefficientMap map) {
this.map = map;
}
....
public double score(IDoubleSource iDblSrc) {
return computeScore(map, iDblSrc);
}
public static double computeScore(MultiKeyCoefficientMap coeffMap, IDoubleSource iDblSrc) {
try {
final Map<String, Double> varMap = new HashMap<String, Double>();
for (Object multiKey : coeffMap.keySet())
{
final String key = (String) ((MultiKey) multiKey).getKey(0);
Enum<?> keyEnum = (Enum<?>) key; //Throws class cast exception
double value = iDblSrc.getDoubleValue(keyEnum);
varMap.put(key, value);
}
return computeScore(coeffMap, varMap);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
return 0;
}
}
}
public static double computeScore(MultiKeyCoefficientMap amap, Map<String, Double> values)
{
//Do some stuff
}
I'm very grateful that you've taken the time to read through this code. Please do let me know if you have any idea what I'm doing wrong!
Many Thanks and Best Wishes,
R
The key incorrect assumption you have is that the IDoubleSource.Variables enum is connected in some way to the Person.Variables enum. They're totally unrelated. (They just happen to have the same simple name.)
When a class (like Person) implements an interface (like IDoubleSource), that class is declaring that it will provide implementations of the (non-default) methods in that interface. Any inner classes, inner enums, or inner interfaces within the implemented interface are only relevant if they appear in the signatures of one of the interface methods that must be implemented.
So you could change your interface to:
public interface IDoubleSource {
public enum Variables {
Default;
}
public double getDoubleValue(Variables variableID);
}
... but then the only legal value to pass in to any implementation of getDoubleValue is Default -- implementors of IDoubleSource can't extend the set of allowed enum values.
I think what you really want to do is to declare that implementors of IDoubleSource must declare what type of enum they deal in:
public interface IDoubleSource<T extends Variables & Enum<T>> {
public interface Variables { }
public double getDoubleValue(T variableID);
}
What you're saying here is that an implementor of the getDoubleValue() method must use some enum type as its arg, and that type must also implement the Variables interface. (If there are no meaningful methods to put in that inner inteface, you can drop it for simplicity.)
Then your implementation would look like this:
public class Person implements IDoubleSource<PersonVariables> {
public enum PersonVariables implements Variables {
nChildren,
durationInCouple,
ageDiff;
}
public double getDoubleValue(PersonVariables variableID) {
switch (variableID) { //no cast necessary here!
case nChildren:
// ...
default:
// this is now really impossible
// if the rest of your program has no unsafe casts
throw new IllegalArgumentException("Unsupported variable");
}
}
}
The last trick, then, is to enhance the signature of your computeScore method to ensure that the iDblSrc argument uses the same enum type as those found in the map:
public static <T extends IDoubleSource.Variable & Enum<T>>
double computeScore(MultiKeyCoefficientMap<T,?> coeffMap,
IDoubleSource<T> iDblSrc);
Then the keys in the map won't be Strings at all, but rather instances of the right enum type.
There are multiple problems here:
An enum declared in an interface (or class) implemented (extended) by another class is NOT overridden by the implementing class. So what you have above is two completely different enums, which happen to have the same local name. But one is IDoubleSource.Variables, with one value: IDoubleSource.Variables.Default, and the other is Person.Variables, with three values, one of which is Person.Variables.nChildren
As the OP pointed out, you cannot simply cast a String (which presumably has a value matching the name of some enum) to an enum, and have it resolve to the expected enum value.
Given these two things, and that it seems you want to select different processing for subtype specific types of things, then at worst, you could pass the string key as an argument, and then vary the logic internally. But really, you have come up with a scheme where you need to have knowledge of the subtype in order to request appropriate (supported) processing. This does not allow for the type of decoupling that is intended when using an interface/implementing class(es). You may want to review the objectives here and work out a better design.
I have been trying to create a comparator through a field of an object, and I can't seem to be able to morph the comparator's type to what I want.
I'm trying to do something like this:
public class Sort {
private ArrayList list;
public Class<?> type;
private Object obj = "Continent";
Sort(ArrayList list, String type) throws ClassNotFoundException
{
this.list = list;
this.type = Class.forName(type);
}
Comparator a = new Comparator<this.type>(){
#Override
public int compare(b.area o1, b.area o2) {
// TODO Auto-generated method stub
return 0;
}
};
is it possible or would I need to write out the methods for each individual class case?
Part I
is it possible [...]?
Not the way you're trying it. You're confusing compile time and run time, i.e.:
Generics are a pure compile time concept in Java. In fact, the generic type is removed during compilation (that's called type erasure). It only exists to give you type safety before compilation, meaning while writing your code.
But the instance type is only assigned at run time. And because you don't know its type during compile time, you had to use a wildcard generic for it. So you only know the type, when you're executing your code.
So you can see that you can't use the information you gathered while executing your code to help you write it.
I highly recommend you read Oracle's tutorial on generics.
Part II
would I need to write out the methods for each individual class case?
I'm with Paul on this. I'm sure we can help you but you should give us an idea of what you're trying to accomplish.
...
Based on on your comment, I think the following would be a good solution.
Your model of the reality consists of continents, countries and cities. Hence you should have classes Continent, Country and City. Since you're modeling population, all of them should have a method getPopulation(). And this is one thing they have in common; all of those things are populated. The way to address this common structure / behavior in Java is to create an interface (let's call it Populated) with a method getPopulation() and have all of those classes implement it:
public interface Populated {
int getPopulation();
}
public class Country implements Populated {
#Override
public int getPopulation() {
...
}
}
// same for Continent and City
Now you have three classes but they can all be treated as one thing, as being populated. For example you can collect them in a list:
List<Populated> populated = new ArrayList<>();
populated.add(new Country());
populated.add(new City());
...
And this list can be sorted with a comparator which works for instances of Populated:
public class PopulationComparator implements Comparator<Populated> {
public int compare(Populated left, Populated right) {
return left.getPopulation() - right.getPopultion();
}
}
Suppose I have the following class (for demonstration purposes)
package flourish.lang.data;
public class Toyset implements Comparable<Toyset> {
private Comparable<?>[] trains;
#Override
public int compareTo(Toyset o) {
for (int i =0; i<trains.length; i++) {
if (trains[i].compareTo(o.trains[i]) < 0)
return -1;
}
return 1;
}
}
The compiler tells me
"The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)"
How can I deal with the fact that I want to put different Comparables into trains?
Sure I could remove the parameters and go with raw types, but that seems like a little bit of a cop-out.
EDIT:
Perhaps the example I've given is a little obtuse. What I'm trying to understand is whether generics should always be used with Comparables. e.g. If the class of the object I want compare is not known until runtime:
public class ComparisonTool {
public static int compareSomeObjects(final Class<? extends Comparable> clazz, final Object o1, final Object o2) {
return clazz.cast(o1).compareTo(clazz.cast(o2));
}
public static void main(String[] args) {
System.out.println(compareSomeObjects(Integer.class, new Integer(22), new Integer(33)));
}
}
If I replace Comparable with Comparable<?> then the compiler complains (as above) because the two cast operations are not guaranteed to be the same class (capture#1 of ? vs capture#2 of ?). On the other hand, I can't replace them with Comparable<Object> either, because then the call in main() doesn't match the method signature (i.e. Integer implements Comparable<Integer> and not Comparable<Object>. Using the raw type certainly 'works', but is this the right approach?
The problem is that one instance might have a Comparable<TrainA> and the other contain Comapable<TrainB> and the compare method of Comparable<TrainA> will not accept an instance of TrainB. This is what you have set up with the wildcard.
Your better bet is to put a common super type in the Comparable ie. Comparable<Toy> or Comparable<Object>.
By declaring your trains field to be of type Comparable<?>[], you're asserting that it's an array of some specific type—and that you don't happen to know which type it is. Two different instances of Toyset will each have trains fields that hold sequences of some specific type, but each has a different specific type in mind. The compiler is warning you that there's nothing in the code asserting that the specific types of the arrays pointed to be the various trains fields in Toyset instances will have any subtype or supertype relationship.
In this case, falling back to a raw type is honest; you don't have anything meaningful to say about the type of objects being compared. You could instead try using Comparable<Object>, which allows rather weak use of a type parameter.
The design strikes me as odd. I'm assuming it's elided from something much larger. Toy sets can be compared, which in turn depends on a lexicographic comparison of the trains contained in each toy set. That's fine, but why is there no upper bound type that all trains have in common?