Questions - TongtongLan/Java GitHub Wiki
1. Java – Constructor in an Interface?
2. What is Marker Interface
3. Can we Overload static methods in Java
4. Can we Override static methods in Java
5. Abstract Class in Java
6. how System.out.println() method works ?
7. How to make a class Immutable in Java
8. Difference Between Interface and Abstract Class in Java
9. How to Generate SerialVersionUID in Java
10. Serialization and Deserialization in Java
11. Java Autoboxing and Unboxing
12. How HashMap works in Java
13. Difference between Enumeration and Iterator ?
14. Sort Objects in a ArrayList using Java Comparable Interface
15. Sort Objects in a ArrayList using Java Comparator
In order to call a method we need object, since the methods in the interface doesn’t have body there is no need for calling the methods in the Interface. Since we cannot call the methods in the interface, there is no need for creating object for the interface and there is no need for having a constructor in it(Constructors will be called during object creation).Constructors belongs to implementations. An interface, on the other hand is a “contract” for a class that implements it.
A Marker interface is a interface with no variables and methods, in simple words, we can say that empty interface in java is called marker interface. Serializable, Cloneable, Remote Interface are some of the examples of Marker Interface. In this article, we will discuss the uses of Marker interface in Java.
When we look closely the marker interface doesn’t have any methods in it, so then comes the question what is the use of it then? If you look closely Serializable, Cloneable, Remote Interface it looks like they will indicate something to compiler or JVM. So if the JVM sees Clonnable it performs some operation to support cloning. Same applies to the Serializable and other marker interfaces as well.
So now we know the what is the use of a marker interface, now again comes a question that why it cannot be done using a flag variable. Yes, you can do it using a flag variable but by using a Marker Interface you can have a more readable code. Later from java 1.5, the need for the marker interface is eliminated by the introduction of Java Annotation feature. It will be a good option to use the annotation rather than marker interface as annotations will have more advantages than a marker interface.
- java.lang.Cloneable
- java.util.EventListener
- java.io.Serializable
- java.rmi.Remote
Yes, you can overload a static method in Java. Java Method Overloading is one of the feature in OOPs concept which allows you to have two or more methods with same method name with difference in the parameters in other words, we can also call this phenomena as Compile time polymorphism.
We cannot overload two methods which differs in static keyword but has the same method signature. When we try to do so we will be getting ” Cannot make a static reference to the non-static method “ error.
CODE example
package com.javainterviewpoint;
public class OverloadExample {
public void disp()
{
System.out.println("Non static disp() method called");
}
public static void disp()
{
System.out.println("static disp() method called121");
}
public static void main(String args[])
{
//Calling the disp() method
OverloadExample.disp();
}
}
Running the above code will lead to the below exception
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Cannot make a static reference to the non-static method disp() from the type OverloadExample
at com.javainterviewpoint.OverloadExample.main(OverloadExample.java:21)
No, We cannot Override a static method in Java. Unlike Overloading of static method we cannot do overriding. When we declare a method with same signature and static in both Parent and Child class then it is not considered as Method Overriding as there will not be any Run-time Polymorphism happening.
When the Child class also has defined the same static method like Parent class, then the method in the Child class hides the method in the Parent class. In the below code we can see that we are having a static display() method in both Parent and Child class.
code example
package com.javainterviewpoint;
import java.io.IOException;
class Parent {
public static void display()
{
System.out.println("Welcome to Parent Class");
}
}
public class Child extends Parent{
public static void display()
{
System.out.println("Welcome to Child class");
}
public static void main(String args[])
{
//Assign Child class object to Parent reference
Parent pc = new Child();
pc.display();
}
}
Output :
Welcome to Parent Class
As per overriding in Java, the display() method of the Child class should be called, since it is a static method overriding will not happen here and hence the Parent class display() method is called here.
The abstract keyword can only be used on classes and methods in Java. An abstract class cannot be instantiated and an abstract method can have no implementation. Let’s dig further.
When a class is declared with abstract keyword then that particular class cannot be instantiated.It can only be extended and the all the methods of the abstract class needs to be implemented by the class which extends our abstract class
An abstract class can have both abstract or non-abstract methods as well
When a method has abstract keyword then the class should definitely be an abstract class and when a method is declared abstract then it cannot have implementation.
An abstract class can have constructor, abstract method, non abstract method , data member and even main method as well.
-
If we have declared a method as abstract then you must declare the class as abstract, abstract method cannot be present in a non-abstract class.
-
Abstract Class can have concrete methods(non-abstract) as well.
-
Abstract method should not have implementation(no body).
-
Abstract method declaration should end with a semicolon (;)
-
The class extending the abstract class should implement all the abstract methods.(如果你的抽象类的派生类有任何一个纯虚函数没有实现,那么不管其他做的再多,这个类仍然是一个抽象类。)
抽象类不能被实例化,匿名内部类可以实例化是因为此匿名内部类实现了抽象类的方法,即是其子类。
- ‘out’ is a static final reference of the PrintStream class declared in the System class.
public final static PrintStream out = null;
- ‘out’ is initialized through the setOut() method which is called inisde initializeSystemClass() method of the System class.
code
private static native void setOut0(PrintStream out);
private static void initializeSystemClass() {
......
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
......
}
- Finally about println(), it is the method which is declared inside the PrintStream class
Immutable class is the one whose state cannot be changed after it is created. The best example for this is String,Integer class in Java, once instantiated the value never be changed.
Immutable class has lots of advantages such as they can be used for the caching purposes as you don’t need to worry about the value changes. Immutable class is thread-safe and hence you don’t need to worry about synchronization issues and can be easily used in the multi-threaded environment.
You can make the class immutable easily by following the below pointers
- Don’t provide “setter” methods or methods that modify fields or objects referred to by fields.
As the setter method will allow you to change the state of the object and hence avoid it.
- Make all fields final and private.
Making the fields private will let you access the fields only within the class and final keyword will let you prevent the value being changed at any cost. This increases your immutability feature.
- Prevent overriding
The best way to prevent overriding is declaring your class as a final class.
- Factory method instance creation and Private Constructor
Use factory based instance creation, have a public method to get the object instances. Private Constructor will never allow object creation for your class
- Never pass the reference of the Mutable objects
Immutable object like String,Integer can be passed directly whereas never pass the direct reference of the mutable object, instead create a copy and pass it
Let put all these and create the immutable class.
import java.util.Date;
public final class ImmutableClassExample
{
//Both String and Integer is Immutable
private final String val1;
private final Integer val2;
//Date is a Mutable field
private final Date date1;
public ImmutableClassExample(String val1,Integer val2,Date date1)
{
this.val1=val1;
this.val2=val2;
this.date1=new Date(date1.getTime());
}
public String getVal1()
{
return val1;
}
public Integer getVal2()
{
return val2;
}
public Date getDate()
{
return new Date(date1.getTime());
}
public static ImmutableClassExample getImmutableClassExampleObject(String a,Integer b,Date c)
{
return new ImmutableClassExample(a,b,c);
}
public String toString()
{
return val1+" --- "+val2+" --- "+date1;
}
}
Testing our immutable class
import java.util.Date;
public class ImmutableTestMain
{
public static void main(String[] args)
{
ImmutableClassExample ic =ImmutableClassExample.getImmutableClassExampleObject("Java",1,new Date());
System.out.println(ic);
ImmutableTestMain.changeValues(ic.getVal1(),ic.getVal2(),ic.getDate());
System.out.println(ic);
}
public static void changeValues(String val1,Integer val2,Date d)
{
val1="interview";
val2=100;
d.setDate(10);
}
}
You will get the output as
Java --- 1 --- Thu Apr 10 15:43:25 IST 2014
Java --- 1 --- Thu Apr 10 15:43:25 IST 2014
-
The main difference is that the Interfaces are implicitly abstract and cannot have implementation, whereas an abstract class can have a concrete class.
-
Interface is implemented using the “implements” keyword. Abstract class can be extended using the “extends” keyword.
-
All the variables in an Interface are by default Static and Final whereas an Abstract can have other access specifiers as well.
-
The methods in an Interface are by default Public but Abstract class can have non-public(private, protected..) methods too.
-
An Interface can extend other Interfaces only but an Abstract class can extend other java classes and implement interfaces.
-
Interfaces are absolutely abstract and cannot be instantiated, als0 an abstract class cannot be instantiated but it can be run if it has a main() method. The below code will get executed successfully and will give you the output as “Inside Main method” and followed by “Abstract method called”. So Abstract class can have a main method but still you cannot instantiate the class.
-
A Java class can implement multiple interfaces but can extend only one abstract class.
You can use interfaces when you want a full implementation and use abstract classes when you want partial implementation for your design.
SerialVersionUID ensures that we are de-serializing the same class which we serialized already. As serialization will allow only the below changes to the Serialized class before de-serializing.
-
Add new variables to the class.
-
Changing a transient variable to a non-transient variable
-
Changing the static variable to a non-static variable.
- Using serialver command
Command : serialver <<class name>>
D:\Jackson>serialver Employee
Employee: static final long serialVersionUID = -136067348552556409L;
- Using Eclipse IDE
Hover the mouse over the Serialization Class or select the class name and press “ctrl+1”
- Generating SerialVersionUID Manually
You can give in your own number just append L at the end
private static final long serialVersionUID = 1L;
Java Serialization allows us to convert Java Object to a Stream of bytes which we can send through a network or save in a flat file or even in a DB for future usage.Deserialization is the process of converting a stream of bytes back to Java Object which can be used in our program. We will be implementing java.io.Serializable interface to achieve serialization
The serializable interface in java is a marker interface(method with no body). It adds serialization capabilities to the class Employee. Even though it is a marker interface it must be implemented in the class whose object you want to persist.
code example
import java.io.Serializable;
public class Employee implements Serializable
{
private int empId;
private String empName;
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
public Employee(int empId,String empName)
{
this.empId=empId;
this.empName=empName;
}
}
We will be using java.util.ObjectOutputStream and java.util.ObjectInputStream to write/read object to/from the file “Persist.txt”
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializationUtility
{
//Method to serialize and save the object in the file
public void serialize(Object obj,String filePath)
{
try
{
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(obj);
outputStream.flush();
outputStream.close();
}
catch(Exception ee)
{
ee.printStackTrace();
}
}
//Method to deserialize and return the object
public Object deSerialize(String filePath)
{
Object obj = null;
try
{
FileInputStream fileInputStream = new FileInputStream(filePath);
ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
obj = inputStream.readObject();
}
catch(Exception ee)
{
ee.printStackTrace();
}
return obj;
}
}
Our SerializationUtility class has two methods
-
serialize() : we will make use of java.util.ObjectOutput stream to write the Object which we pass, to the file “Persist.txt”
-
deSerialize(): java.util.ObjectInputStream is used to read the Object from the file and return it back to the user. Client.java
public class Client { public static void main(String args[]) { //Path to store the Serialized object String filePath="D://Persist.txt"; Employee emp = new Employee(1,"JavaInterviewPoint");
SerializationUtility su = new SerializationUtility(); //Serialize emp object su.serialize(emp, filePath); //De-Serialize Employee object Employee ee = (Employee)su.deSerialize(filePath); System.out.println("Employee id : "+ee.getEmpId()); System.out.println("Employee Name : "+ee.getEmpName());} }
In our Client.java we have called the serialize() and deSerialize() methods. When we run the above program we will get the output as below and you will have physical file created at your D: Drive
Employee id : 1
Employee Name : JavaInterviewPoint
If the parent class is Serializable then all the sub class which extends our parent class will be Serializable as well.
If we have a non-serializable reference of a class inside a Serializable class, then serialization operation will not be performed.In such case, NonSerializableException will be thrown. Let’s look into the below code.
Employee class is Serializable
public class Employee implements Serializable
{
private static final long serialVersionUID = 5414347551602268992L;
private int empId;
private String empName;
Location l;
public static long getSerialversionuid() {
return serialVersionUID;
}
public Location getL() {
return l;
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
public Employee(int empId,String empName,Location l)
{
this.empId=empId;
this.empName=empName;
this.l = l;
l.setAddress("Chennai");
}
}
Location class is non Serializable
public class Location
{
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Client
public class Client
{
public static void main(String args[])
{
//Path to store the Serialized object
String filePath="c://Persist.txt";
Employee emp = new Employee(1,"JavaInterviewPoint",new Location());
SerializationUtility su = new SerializationUtility();
//Serialize emp object
su.serialize(emp, filePath);
//De-Serialize Employee object
Employee ee = (Employee)su.deSerialize(filePath);
System.out.println("Employee id : "+ee.getEmpId());
System.out.println("Employee Name : "+ee.getEmpName());
System.out.println("Location : "+ee.getL().getAddress());
}
}
Now when we run our Client.java we will get java.io.NotSerilizableException
Autoboxing and Unboxing are the features included in Java 1.5, where the auto conversion happens from Primitive data type to its corresponding Wrapper Class and Vice-Versa. Autoboxing features allows you to use the primitive data type and object types interchangeably in Java in many places. The most familiar case is that when we use Collections like ArrayList or TreeSet etc.. we all know that it can take only Object data types and not primitive types, then we need to convert primitive to object type and add it to the collection. With the introduction of autoboxing and unboxing the conversion happens automatically by the Java compiler.
Conversion of the primitive data types to their corresponding wrapper classes is known as autoboxing.
- Adding values to the collection framework
We all know that collection can take only Object type and not primitive type, even when you add primitives to the collection, the compiler will not throw any error it will do the conversion(Autoboxing) for you.
code example
ArrayList<Integer> arrayList1 = new ArrayList<Integer>();
arrayList1.add(1);
arrayList1.add(2);
arrayList1.add(3);
- Parameter to a Method
When a method is expecting a parameter of Wrapper class type but the parameter passed is of primitive type.
code example
public class Test1
{
public static void main(String args[])
{
disp(10);
}
public static void disp(Integer val)
{
System.out.println(val);
}
}
- Assigning Primitives to Wrapper
When you are assigning a primitive type value to wrapper class of its type. For example: The below statements are completely valid
Float f = 3.0f;
Integer i = 3;
It is just the reverse process of autoboxing. Automatically converting an object of a wrapper class to its corresponding primitive type is known as unboxing. For example : conversion of Integer to int, Float to float, Double to double etc.
- Retrieving value from the Collection Framework
The get() Method of the collection will return Wrapper class still you can assign it to primitives.
code example
ArrayList<Integer> arrayList1 = new ArrayList<Integer>();
int val = arrayList1.get(0);
Here the arrayList1 returns Integer type object, which compiler unboxes and sets to int val
- Parameter to a Method
When a method is expecting a parameter of primitive type but the parameter passed is of Wrapper class type.
code example
public class Test1
{
public static void main(String args[])
{
disp(new Integer(10));
}
public static void disp(int val)
{
System.out.println(val);
}
}
Even though the disp() method expects a primitive(int) parameter, but we are passing wrapper class type(Integer) . The program runs fine as the compiler does the Unboxing here.
- Assigning Wrapper to Primitives
When you are assigning a wrapper type to primitives. For example: The below statements are completely valid
Integer wrapper = new Integer(10);
int i = wrapper;
- Autoboxing
What we are able to see
Interger val = 10;
What compiler does for us
Integer val = Integer.valueOf(10);
- Unboxing
What we are able to see
Integer wrapper = new Integer(10);
int val = wrapper;
What compiler does for us
Integer wrapper = new Integer(10);
int val = wrapper.intValue();
- 下面这段代码的输出结果是什么?
code example
public class Main {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2);
System.out.println(i3==i4);
}
}
output:true false
输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。此时只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现:
Integer.java
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
IntegerCache.java
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。
- 下面这段代码的输出结果是什么?
code example
public class Main {
public static void main(String[] args) {
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2);
System.out.println(i3==i4);
}
}
output:false false
为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
看源码可得出结论:
-
Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
-
Double、Float的valueOf方法的实现是类似的。
- 下面这段代码输出结果是什么:
code example
public class Main {
public static void main(String[] args) {
Boolean i1 = false;
Boolean i2 = false;
Boolean i3 = true;
Boolean i4 = true;
System.out.println(i1==i2);
System.out.println(i3==i4);
}
}
output:true true
Boolean.java
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
在Boolean中定义了2个静态成员属性:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
- 谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。
-
第一种方式不会触发自动装箱的过程;而第二种方式会触发;
-
在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)——大概是因为第二种方式调用了valueOf(int)方法,只有参数不再-127到127范围内才会通过构造器方法 new Integer(xxx) 来创建一个对象,否则会使用cache。第一种方法直接调用了构造器方法创建一个Integer对象。
- 下面程序的输出结果是什么?
code example
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);
System.out.println(e==f);
System.out.println(c==(a+b));
System.out.println(c.equals(a+b));
System.out.println(g==(a+b));
System.out.println(g.equals(a+b));
System.out.println(g.equals(a+h));
}
}
output:true false true true true false true
当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。
The answer to the question how does a hashmap works is that is it works based on the hashing principle but it is not as simple as it sounds. Hashing is the mechanism of assigning the unique code to a variable or attribute using some algorithm to enable easy retrieval. A true hashing mechanism should always return the same hashCode() when it is applied to the same object.
HashMap.java 中
transient Node<K,V>[] table;
the HashMap stores the Objects as Node<K,V> instances, not as key and value.
The HashMap has an inner class called as Node Class which hold the key, value stuff. And there is something called as next, hash which you will get to know a bit later.
Code
static class Node<K,V> implements Map.Entry<K,V>
{
final K key;
V value;
Entry<K,V> next;
final int hash;
........
}
As of now, you know that the hashmap stores the Entry instances in an array and not as a key,value pairs.
The Code implementation of the put method will be like below
public V put(K key, V value)
{
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next)
{
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
{
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
-
First, it checks for the if the key given is null or not, if the given key is null it will be stored in the ‘0’th position as the hashcode of null will be zero.
-
Then it applies the hashcode to the key.hashCode() by calling the hashcode method. In order to get the value within the limits of an array the hash(key.hashCode())is called which does some shifting operations to the hashcode.
-
The indexFor() method is used to get the exact location to store the Entry object.
-
Then comes the most important part what happens if two different object has the same hashcode( eg : Aa,BB will have the same hashcode) and will it be stored in the same bucket. To handle this let’s think of the LinkedList in data structure it will have a next attribute which will always point to the next object . The same way the next attribute in the Entry class points to the next object. Using this different objects with the same hashcode will be placed next to each other.
-
In the case of the Collision , the HashMap checks for the value of the next attribute if it is null it inserts the Entry object in that location , if next attribute is not null then it keeps the loop running till next attribute is null then stores the Entry object there.
As we all know hashmap doesn’t allow duplicates in the key even though we insert the same key with different values the latest value only is returned.
import java.util.HashMap;
import java.util.Map;
public class HashMapEg
{
public static void main(String[] args)
{
Map map = new HashMap();
map.put(1,"sam");
map.put(1,"Ian");
map.put(1,"Scott");
map.put(null,"asdf");
System.out.println(map);
}
}
For the above code, you will get the output as {null=asdf, 1=Scott} as the values sam,Ian will be replaced by Scott , So how does this happen.
All the Entry Objects in the LinkedList will have the same hashcode but hashmap uses equals () method checks the equality if key.equals(k) is true then it will replace the value object inside the Entry class and not the key. So this way it prevents the duplicate key being inserted.
It is almost the same logic as applied in put will be used to retrieve the value.
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
-
First, it gets the hashcode of the key object which is passed and finds the bucket location.
-
If the correct bucket is found it returns the value (e.value)
-
If no match is found it returns null.
The same collision resolution mechanism will be used here key.equals(k) will check until it is true, if true it returns the value of it.
Both Enumeration and Iterator is used for traversing through the underlying Collection. Enumeration can traverse limited collection such as Vectors and HashTable. Whereas Iterator can be used to almost all the Collection. Enumeration is twice as fast as Iterator as it act as read-only interface on the other hand Iterator is much safer as it doesn’t allow any modification to the underlying collection when iterating if any modification occurred it will throw ConcurrentModificationException and hence the Iterators are called as fail-fast Iterator as they fail quickly when it encounters a change.
Since Enumeration act as the read-only interface it can simply traverse through the Collection. It doesn’t have any methods to add or remove objects from the collection. Enumeration has 2 Major Methods to traverse hasMoreElements(),nextElement().
Using the Iterator you can make modification the Collection which you are iterating. Iterator has remove() which lets you remove the object from the collection even when we are iterating without any ConcurrentModificationException.
Using the Comparable interface is almost the same as the previous, but here instead of a separate class for implementing the Comparator interface we can implement it in the same Employee Class by overriding the compareTo() method instead of the compare() method. Let see how the objects are sorted using the Comparable interface.
code example
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortObj {
public static void main(String args[]) {
List l = new ArrayList();
l.add(new Employee(20, "javainterviewpoint"));
l.add(new Employee(10, "javainterview"));
l.add(new Employee(30, "jip"));
Collections.sort(l);
System.out.println(l);
}
}
class Employee implements Comparable {
private String empname;
private int eid;
public Employee(int eid, String empname) {
this.eid = eid;
this.empname = empname;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public int compareTo(Employee e1) {
// if this.eid is greater than e1's eid then it returns a positive
// interger
// if this.eid is lesser than e1's eid then it returns a negative
// interger
// if this.eid is equal than e1's eid then it returns zero
return (this.getEid() - e1.getEid());
}
public String toString() {
return " \n id : " + this.eid + " empname : " + this.empname;
}
}
In order to sort the List of objects we need to implement either Comparable or Comparator interface. In this tutorial you will learn how to use the Comparator interface. This has a method called compare which lets you search between objects based on its properties.
code example
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortObjectOfList {
public static void main(String args[]) {
List l = new ArrayList();
l.add(new Employee(20, "javainterviewpoint"));
l.add(new Employee(10, "javainterview"));
l.add(new Employee(30, "jip"));
Collections.sort(l, new ComparatorImpl());
System.out.println(l);
}
}
class ComparatorImpl implements Comparator {
public int compare(Employee e1, Employee e2) {
// if e1's id is greater than e2's eid then it returns a positive interger
// if e1's id is lesser than e2's eid then it returns a negative interger
// if e1's id is equal than e2's eid then it returns zero
return (e1.getEid() - e2.getEid());
}
}
class Employee {
private String empname;
private int eid;
public Employee(int eid, String empname) {
this.eid = eid;
this.empname = empname;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String toString() {
return " \n id : " + this.eid + " empname : " + this.empname;
}
}