Morgan Stanley Interview Question
Java DevelopersCountry: India
Nice code Pani.. :)
However; your code would not be able to handle basic types like String, Integers etc. So, you could replace getComparable() code as follows:
private Comparable getComparable(Object o) {
try {
if(!(o instanceof Comparable))
{
Object invoke = o.getClass().getMethod(property, new Class[] {})
.invoke(o, new Class[] {});
return ((Comparable)invoke);
}
else
{
return (Comparable)o;
}
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage());
}
}
Is there any scope to improvise this code.. Suggestions are welcome.
I am confused in line -
Object invoke = o.getClass().getMethod(property, new Class[] {})
.invoke(o, new Class[] {});
return ((Comparable)invoke);
Can you also some insight into the exact Student class
@Nini,
If you observe the code "o.getClass().getMethod(property, new Class[] {})", property states the getter method name of the class considered. So, consider Student class as follows:
public class Student
{
private String name;
Student(){}
Student(String name) {this.name = name;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
"o.getClass().getMethod(getName, new Class[] {})" would get "getName" method on current object i.e. Student. And ".invoke(o, new Class[] {})" would invoke the same which would return String which can be saved in Object variable and later typecasted as Comparable.
Use reflections...
This code is written under following assumptions:
> The objects to be compared should conform to JavaBean Conventions (should have getter methods atleast to all fields to be compared with)
> Currently would be able to handle basic types like String, int and float only (need to add code to handle all comparable types). I am unable to generalise the code to handle all Comparable types. Would appreciate if someone come with the solution for the same.
> I know my code is very crude. Would appreciate if someone would improvise this code that would comply with ethical coding conventions. Also, I believe implementing generics may help. I am unable to come up with that solution though.
> This code is currently comparing all the available field in JavaBean
public class AllComparator implements Comparator<Object> {
public static boolean isGetter(Method method) {
if (!method.getName().startsWith("get")) {
return false;
}
if (method.getParameterTypes().length != 0) {
return false;
}
if (void.class.equals(method.getReturnType())) {
return false;
}
return true;
}
@Override
public int compare(Object o1, Object o2) {
if (o1.getClass().toString().equals("class java.lang.String")) {
return ((String) o1).compareTo((String) o2);
} else if (o1.getClass().toString().equals("class java.lang.Integer")) {
return ((Integer) o1).compareTo((Integer) o2);
} else if (o1.getClass().toString().equals("class java.lang.Float")) {
return ((Float) o1).compareTo((Float) o2);
} else {
Method[] methods = o1.getClass().getMethods();
int greater = 0;
int lesser = 0;
int equals = 0;
int result = 0;
String retType = null;
for (Method method : methods) {
if (isGetter(method)) {
Object obj1 = null, obj2 = null;
try {
obj1 = method.invoke(o1);
obj2 = method.invoke(o2);
} catch (Exception ex) {
ex.printStackTrace();
}
retType = method.getReturnType().toString();
if (retType.equals("float")) {
// try{
float x = Float.parseFloat(obj1.toString());
float y = Float.parseFloat(obj2.toString());
result = (x > y) ? 1 : (x == y) ? 0 : (-1);
if (result > 0) {
greater++;
}
if (result < 0) {
lesser++;
}
if (result == 0) {
equals++;
}
} else if (retType.equals("int")) {
int x = Integer.parseInt(obj1.toString());
int y = Integer.parseInt(obj2.toString());
result = (x > y) ? 1 : (x == y) ? 0 : (-1);
if (result > 0) {
greater++;
}
if (result < 0) {
lesser++;
}
if (result == 0) {
equals++;
}
} else if (retType.equals("class java.lang.String")) {
String x = obj1.toString();
String y = obj2.toString();
result = x.compareTo(y);
if (result > 0) {
greater++;
}
if (result < 0) {
lesser++;
}
if (result == 0) {
equals++;
}
}
}
}
if (lesser > greater) {
if (lesser > equals) {
return -1;
} else {
return 0;
}
} else {
if (greater > equals) {
return 1;
} else {
return 0;
}
}
}
}
}
class Bean001 {
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public float getC() {
return c;
}
public void setC(float c) {
this.c = c;
}
private int a;
private String b;
private float c;
}
public class AllComparatorTester {
public static void main(String[] args) {
ArrayList al = new ArrayList();
Bean001 b1 = new Bean001();
b1.setA(2);
b1.setB("b");
b1.setC(3.14f);
al.add(b1);
// al.add(2);
Bean001 b2 = new Bean001();
b2.setA(1);
b2.setB("a");
b2.setC(1.5f);
al.add(b2);
// al.add(1);
// System.out.println("arrayList before sorting.." + al);
// java.util.Collections.sort(al, new AllComparator());
// System.out.println("arrayList after sorting.." + al);
Bean001 x;
System.out.println("arrayList before sorting..");
for (Object o : al) {
x = (Bean001) o;
System.out.println(x.getA() + " " + x.getB() + " " + x.getC());
}
System.out.println("After sorting...");
java.util.Collections.sort(al, new AllComparator());
for (Object o : al) {
x = (Bean001) o;
System.out.println(x.getA() + " " + x.getB() + " " + x.getC());
}
}
}
Comparator to compare any type of object you can do so by checking instanceof Integer or String, but suppose two objects are completely different, such as one Integer and one String, in that case it does not make any sense to have such comparator.
Compare the memory addresses of the objects!
OR
In Java you can compare the hash codes of the objects.
if(obj1.hashCode() > obj2.hashCode()) {
return true; //obj1 is greater than obj2
}
You need to use reflection.. This comparator code can be used for any type which implements Comparable interface
- Pani Dhakshnamurthy September 28, 2013