When you are simple moving through List but you are not modifying the List object foreach is more efficient.In case you want to perform operations on each element of list individually taking out the element in such case use Iterator.

List<Fruits> arrFruits = new ArrayList<Fruits>();
Iterator<Fruits> itFrt = arrFruits.iterator();

while(itFrt.hasNext())
{
 Fruits frt = itFrt.next();
 System.out.println(frt);
}

ListIterator

  • While using Iterator in particular to List using a ListIterator is more powerful over Iterator.
  • ListIterator is bidirectional
  • It also keep track of Indexes of next and previous elements
  • It can replace last element it visited using set method
 List<fruits> arrFruits     = fruits.arrayList(5);
 ListIterator<fruits> itFrt = arrFruits.listIterator();

 while(itFrt.hasNext())
 {
   System.out.println(it.next()); 
   System.out.println(it.nextIndex()); 
   System.out.println(it.previousIndex()); 
 }
  • List maintains elements in Particular Sequence.
  • Two types of List 1.ArrayList and 2.LinkedList
  • ArrayList is faster while accessing elements but slower while Insertion and Deletion
  • LinkedList is slow in random access but faster during insertion and deletion

Operations in ArrayList

class Fruits
{	
  String Name = "Fruit";
}

class Apple extends Fruits
{	
 public Apple()
 {
   Name = "Apple";
 }
}

class Orange extends Fruits
{	
 public Orange()
 {
  Name = "Orange";
 }
}

class Mango extends Fruits
{	
 public Mango()
 {
  Name = "Mango";
 }
}

Adding Element – List.add()

List<Fruits> arrFruits = new ArrayList<Fruits>();
Fruits objApple  = new Apple();
Fruits objMango  = new Mango();
arrFruits.add(objApple);
arrFruits.add(objMango);

Removing Element – List.remove()

arrFruits.remove(objApple);

Removing by Index – List.remove()

arrFruits.remove(1);

Index of Element – List.indexOf()

arrFruits.indexOf(objMango);

Index of Element – List.indexOf()

arrFruits.indexOf(objMango);

SubList – List.subList(StartPOS, EndPOS)

List<Fruits> arrNewFruits = arrFruits.subList(0,2);

containsAll – NewList.containsAll(OrgList)

 arrNewFruits.containsAll(arrFruits);

set Value at Index

 arrNewFruits.set(1, new Orange());

removeAll

 arrFruits.removeAll(arrFruits);

addAll

 arrFruits.addAll(arrNewFruits);

retainAll – set Intersection Operation
retainAll performs set Interscetion Operation by taking Two ArrayList. It Retains Boolean true if intersection finds element false otherwise.

List<Integer> arrNums1 = new ArrayList<Integer>();
arrNums1.add(1);
arrNums1.add(2);
arrNums1.add(3);
		
List<Integer> arrNums2 = new ArrayList<Integer>();
arrNums2.add(1);

System.out.println(arrNums1.retainAll(arrNums2));
System.out.println(arrNums1);

Consider the Following Example

 Collection<Integer> coll = new ArrayList<Integer>();

 coll.addAll(Arrays.asList(1,2,3,4,5));

In the above addAll the addition takes place in following steps as Below
1.varargs+autoboxing creates Integer[]
2.Arrays.asList creates a List backed by the array
3.addAll iterates over a Collection using Iterator

Now consider the Below Code

 Collection<Integer> coll = new ArrayList<Integer>();

 coll.addAll(coll, 1,2,3,4,5);

1.varargs+autoboxing creates Integer[]
2.addAll iterates over an array (instead of an Iterable)

We can see now that b) may be faster because:

Arrays.asList call is skipped, i.e. no intermediary List is created.
Since the elements are given in an array, iterating over them may be faster than using Iterator.

I have a Table with rows like one below

Image

I want to have Highest paid employee in Each Department

EmpName      Designation         Salary
Phillipe           Analyst                    3150
Scott              Clerk                        2500
Mac                Manager                  5000

Query 1(Oracle Specific)

SELECT EmpName, Designation, Salary
  FROM (SELECT EmpName, Designation, Salary,
               RANK() OVER (PARTITION BY Designation ORDER BY Salary DESC) AS rn
          FROM Employees)
 WHERE rn = 1
 ORDER BY Designation;

Query 2

 SELECT EmpName, Designation, Salary
   FROM Employees
  WHERE (Designation, Salary) IN (SELECT Designation, MAX(Salary)
                                   FROM Employees
                                  GROUP BY Designation)
 ORDER BY Designation;

Query 3(Oracle Specific)

SELECT max(EmpName) keep (dense_rank last order by salary) AS EmpName,
       Designation, max(Salary) keep (dense_rank last order by salary)  AS Salary
  FROM Employees
 GROUP BY Designation;

Query 4(Oracle Specific)

SELECT max(EmpName) keep (dense_rank last order by salary) AS EmpName,
       Designation, max(Salary) keep (dense_rank last order by salary)  AS Salary
  FROM Employees
 GROUP BY Designation;

Need for Generics
Pre Java 5 Containers allows to insert an incorrect type into a Container.Consider a container you need to store Apple objects in it.The code for scenario is as shown below

public class Generics1
{
  public static void main(String[] args)
  {
    List arrFruits = new ArrayList();
    arrFruits.add(new Apple());
    arrFruits.add(new Mango());
		
    for (Object object : arrFruits)
    {
     System.out.println(((Apple)object).Name);
    }
  }
}

class Apple
{	
  String Name = "Ooty";
}

class Mango
{	
  String Name = "Malgova";
}

Now the above code compiles Perfectly fine.But when you try to run the code you will encounter a problem in casting to Apple class as you added Mango object in to arrFruits.The code compiles without error since every thing you add using add method into ArrayList gets converted to Object before it get Stored.

By Using generics you are preventing the addition of wrong type of Object into the container as Below.

public class Generics1
{	
 public static void main(String[] args)
 {
   List<Apple> arrFruits = new ArrayList<Apple>();
   arrFruits.add(new Apple());
   arrFruits.add(new Mango()); //Compile Time Error
		
   for (Apple object : arrFruits)
   {
     System.out.println(object.Name);
   }
  }
}

You can also see there is no need for Casting while using Generics.

You can also store Subtype of Parent class in Generics as Below

 
public class Generics1
{	
 public static void main(String[] args)
 {
   ArrayList<Fruits> arrFruits = new ArrayList<Fruits>();
   arrFruits.add(new Fruits());
   arrFruits.add(new Apple());
   arrFruits.add(new Orange());
   arrFruits.add(new Mango());
	
   for (Fruits object : arrFruits)
   {
     System.out.println(object.Name);
   }
 }
}

class Fruits
{	
  String Name = "I am Fruit";
}

class Apple extends Fruits
{	
  public Apple()
  {
    Name = "I am Apple";
  }
}

class Orange extends Fruits
{	
  public Orange()
  {
    Name = "I am Orange";
  }
}

class Mango extends Fruits
{	
   public Mango()
   {
     Name = "I am Mango";
   }
}

The Containers can be Broadly Classified in to Two types.

1.Collection
2.Map

The Collection includes the following
1.ArrayList
2.LinkedList
3.HashSet
4.TreeSet
5.LinkedHashSet

The Map includes the following
1.HashMap
2.TreeMap
3.LinkedHashMap

Boxing
Boxing is the process of converting the Primitive type to Reference type

byte to Byte
int to Integer
double to Double
char to Character

Unboxing
Unboxing is the process of converting the Reference type to Primitive type

Byte to byte
Integer to int
Double to double

Consider the Following example

List arrAges = new ArrayList();
arrAges.add(25);
int n = arrAges.get(0);

is equivalent to

List arrAges = new ArrayList();
arrAges.add(new Integer(25));
int n = arrAges.get(0).intValue();

Boxing an int or short value between -128 and 127, a Char value between ‘\u0000’ and ‘\u007f’, byte and boolean

Consider the following example

Integer a = 3;
Integer b = 2;
Integer c = 5;
Integer d = a + b;
System.out.println(c == d);

Output
true
The output is true because the value comparison is taking place instead of object comparison.Boxed values between -128 to 127 are cached. Boxing uses Integer.valueOf method, which uses the cache. Values outside the range are not cached and always created as a new instance. Since your values fall into the cached range, values are equal using == operator.

This is What happening when values boxed are between -128 to 127

Integer a = 3;
Integer b = 2;
Integer c = 5;
Integer c = Integer.valueOf(5);
Integer d = Integer.valueOf(a.intValue() + b.intValue());

Output
true

when you try to add integers which are outside the range as one below

Integer a = 300;
Integer b = 200;
Integer c = 500;
Integer d = a + b;
System.out.println(c == d);

Output
false

How to Check Content in List with String

 List arrNums  = new ArrayList();
 arrNums.add(2);
 arrNums.add(3.14);
 assert arrNums.toString().equals("[2,3.14]");

List is not a Subtype of List
List is a Subtype of Collection

Doesn’t Works

 List ints = Arrays.asList(1,2);
 List nums = ints;  //Not Ok as you try to Assign List to List

The above doesn’t works as you try to add List to List

Works

 List ints1 = Arrays.asList(1,2);
 Collection nums = ints1;

Addition of Subtypes in Supertype in generics is Allowed as Below

List nums = new ArrayList();
List ints2 = Arrays.asList(1,2);
List ints3 = Arrays.asList(3.1,2.15);

nums.add(3.15);
nums.addAll(ints2);
nums.addAll(ints3);

Assignment of Subtype to Supertype is not allowed

 List nums = new ArrayList();
 List ints = Arrays.asList(1,2);
 nums.addAll(ints); //Allowed
 nums = ints; //Not Allowed

Assignment of List to List is Not Allowed

Use extends wildcard when you get values out of Structure and use super wildcard when you put values into structure

 List<? extends Integer> arrNums = new ArrayList();
 List arrInts           = new ArrayList();
 arrInts.add(1);
 arrInts.add(2);
 arrInts.add(3);

 arrNums.addAll(arrInts); //Not Allowed since wildcard is extends(get)

 

 List<? super Integer> arrNums = new ArrayList();
 List arrInts         = new ArrayList();
 arrInts.add(1);
 arrInts.add(2);
 arrInts.add(3);

 arrNums.addAll(arrInts); //Allowed since wildcard is super(put)

 


	
protected void doGet(HttpServletRequest request, 
                     HttpServletResponse response) 
                     throws ServletException, IOException 
{	
   int lngCookieSet    = 0;
   String strCookieVal = "";
   String cookieName   = "Name";
	
   Cookie[] cookies = request.getCookies();
		
   if(cookies != null && cookies.length > 0)
   {
      for(int i=0;i<cookies.length;i++)
      {
        if(cookieName.equals(cookies[i].getName()))
        {
          lngCookieSet = 1;
          strCookieVal = cookies[i].getValue();
        }
      }
   }	
		
   if(lngCookieSet == 1)
   {
     PrintWriter prw = response.getWriter();	
     prw.print(strCookieVal);
   }
   else
   {
     Cookie cook = new Cookie("Name", "Mugil");
     cook.setMaxAge(24*60*60*365);//1 Year
     response.addCookie(cook);	
   }
}

Notes
1. check cookies != null otherwise the compiler will generate null pointer exception
2. The new Cookie constructor will take Cookie Name and Value as Parameter.
3. The addCookie Will add cookie to response Header to set cookie on Client Side

1.Why do they assign an ArrayList to List?.
Assigning List interface is like assigning a Child class object to parent class variable.Here List interface is assigned to ArrayList Class.

List is an interface.The intention of Using a Interface is if you decide to change your implementation later while you code you can change it at the point of creation Like one below

 List<Fruits> arrFruits = new ArrayList<Fruits>();

converted to

 List<Fruits> arrFruits = new LinkedList<Fruits>(); 

2.What is java.util.ConcurrentModificationException
The below code Generate java.util.ConcurrentModificationException

 List<Fruits> arrFruits = new ArrayList<Fruits>();

 Fruits objApple  = new Apple();
 Fruits objOrange = new Orange();
 Fruits objMango  = new Mango();

 arrFruits.add(objApple);
 arrFruits.add(objOrange);
 arrFruits.add(objMango);

 List<Fruits> arrNewFruits = arrFruits.subList(0, 1);
 arrFruits.retainAll(arrNewFruits); 

In your above code examples you I have a big list and the sub-list in reverse order.
When I invoke retainAll() on the sub-list, no modifications will occur.
This is because each element in the sub-list is in the big list.
If no modification occurs, no ConcurrentModificationException will be thrown.


If I reverse the order and invoke retainAll() on the big list, it will get mutated.
This is because not every item in the big list is in the sub-list.
When I remove an element from the big list, a ConcurrentModificationException is thrown.
This is because I cannot mutate a list while iterating over it.

The iteration takes place in the retainAll() method.
In my code, the list argument happens to reference the same list that’s being modified.
This is because of the way List.subList() works:

arrNewFruits.retainAll(arrFruits) //This Works

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.

I should create a new list from the sub-list if there is a chance that either list will get modified while one of the lists is being iterated over.

I can create a new list from the sub-list like below

List<Foo> freshList = new ArrayList<Foo>(bigList.subList(0,2));

Now I can iterate and mutate.

3.In the below code if you try to add number 5 to List it will result in runtime Exception java.lang.UnsupportedOperationException

 List<Integer> arrNums = Arrays.asList(1,2,3,4);

 arrNums.add(5);

Arrays.asList(1,2,3,4) creates a list on an array whose size cannot be changed.does not convert array but ‘represents’ it like a List.But array is under the hood with all its properties like a fixed number of elements. That way we can use and access an array through the List interface.

4.

public static <T> List<T> asList(T... a)

Documentation states that asList returns an object that implements interface java.util.List, nowhere does it says it will return an instance of class java.util.ArrayList.

5.If you want a List generated from asList() method but still want to use add Method

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3,4));

6.I am having a Primitive array as below. Using Arrays.asList method does not return boxed Integer List value.

int[] nums = new int[] { 1, 2, 3 };
Arrays.asList(nums)

One way is to iterate over the primitive array and add elements to Integer ArrayList Manually.

List<Integer> items = new ArrayList<Integer>();

for (Integer item: nums) 
{
  items.add(item);
}

Other way is to use streams as below

int[] nums = new int[] { 1, 2, 3 };
Arrays.stream(nums)
      .boxed()
      .collect(Collectors.toList());

7.Return Types in ArrayList add Method

Test.java

public class Test 
{
  public static void main(String[] args) 
  {		
    List arraList = new ArrayList<String>();
    System.out.println(arraList.add("Mugil"));
  }
}

Output

True

But the below add method is of void return type

public class Test 
{
  public static void main(String[] args) 
  {		
    List arraList = new ArrayList<String>();
    System.out.println(arraList.add(1, "Mugil"));
  }
}

Why it is So?
Collection.add is a pretty generic method (widely applicable). As such, they wanted a return value that would apply generally.

Some classes (like ArrayList) always accept elements irrespective of element already in the list(duplicate element), and so will always return true. In these cases, a return type of void is more then enough.

If a collection refuses to add a particular element for any reason other than that it already contains the element say Set, it must throw an exception (rather than returning false).

So if it returns true, the element was added, if it returns false the element was already there (such as in a Set) and in other cases an exception needs to be thrown (for example if a Collection would limit its size and not block).

Differences is that the contract for add(E) is defined in Collection, whereas add(int index, E e) is defined in the List interface (and doesn’t need to return anything). It could return true as well, but it would be useless. The other method has to return true, because otherwise it would break the contract for Collection.

The way the Set Collection could have been is

if (!set.contains(item)) 
{
    set.add(item);
    itemWasAdded(item);
}

The extra checking of Contains is skipped in below actual java code design

if (set.add(item)) 
{
    itemWasAdded(item);
}

But this check-then-act behavior isn’t thread safe, which can be crucial in multithreaded applications. For instance, it could be that another thread added an equal item between you checking set.contains(item) and the set.add(item) in the first code snippet. In a multithreaded scenario, those two actions really need to be a single, atomic action; returning boolean from the method makes that possible.

8.Iterator vs ListIterator
When you are simple moving through List but you are not modifying the List object foreach is more efficient.In case you want to perform operations on each element of list individually taking out the element in such case use Iterator.

List<Fruits> arrFruits = new ArrayList<Fruits>();
Iterator<Fruits> itFrt = arrFruits.iterator();

while(itFrt.hasNext())
{
 Fruits frt = itFrt.next();
 System.out.println(frt);
}

ListIterator

  • While using Iterator in particular to List using a ListIterator is more powerful over Iterator.
  • ListIterator is bidirectional
  • It also keep track of Indexes of next and previous elements
  • It can replace last element it visited using set method
 List<fruits> arrFruits     = fruits.arrayList(5);
 ListIterator<fruits> itFrt = arrFruits.listIterator();

 while(itFrt.hasNext())
 {
   System.out.println(it.next()); 
   System.out.println(it.nextIndex()); 
   System.out.println(it.previousIndex()); 
 }

Running Iterator Through Bean Stored in Map List

public class Iterator extends ActionSupport
{
   Map nmap = new HashMap<String, List<Person>>();
	
   public String execute()
   {
      Person objPerson    = new Person();

      objPerson.userName  = "Name1";
      objPerson.age 	    = 25;
      List<Person> myList = new ArrayList<Person>();
      myList.add(objPerson);
		
      nmap.put("Mugil", myList);
	
      objPerson.userName   = "Name2";
      objPerson.age 	     = 26;
      List<Person> myList2 = new ArrayList<Person>();
      myList2.add(objPerson);
		
      nmap.put("Mani", myList2);
		
      objPerson.userName    = "Name3";
      objPerson.age 	      = 27;
      List<Person> myList3  = new ArrayList<Person>();
      myList3.add(objPerson);
		
      nmap.put("Vinu", myList3);
		
      setNmap(nmap);
		
      return SUCCESS;
   }
	
   public Map getNmap() 
   {
     return nmap;
   }

   public void setNmap(Map nmap) 
   {
     this.nmap = nmap;
   }
}

Person Bean Code

class Person
{
    String userName;
    int age;

    public int getAge() {
      return age;
    }

    public void setAge(int age) {
      this.age = age;
    }

    public String getUserName() {
      return userName;
    }
	
    public void setUserName(String userName) {
      this.userName = userName;
    }
}

JSP Page Using Struts2 Tag

<table>
<s:iterator value="nmap">
     <s:iterator var="Person" value="value">
      <tr>
     	<td>
    	  <s:property value="key" />	
    	</td>
        <td>
      	  <s:property value="age" />
    	</td>
      </tr>
      </s:iterator>
</s:iterator>
</table>

Once a Time I had a Scenario where I should display a Page with List of employees movement from Last Friday to this week Saturday if Saturday is over(you are in Sunday).If you are in any other day other than Saturday(Mon..Fri) then you should choose date of Last before Saturday to Friday.

The above would be made with the following

Image 1
Image 1

As you can see in the above diagram I have added two calendar.

In First I should Get Date between 15 to 21 since today date is this 28 and Saturday is not over
In Second I should Get Date between 22 to 28 since today date is this 30 nd Saturday is over

  java.util.Date dt    = new java.util.Date();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  String currentTime   = sdf.format(dt);
  Calendar cal         = Calendar.getInstance();

  int daysBackToSat = cal.get(Calendar.DAY_OF_WEEK);
  
  //Checks if this weeks friday is Over.in My Case 28 falls on Friday.
  //Returns 6 the below case is True so adds 13 to get before Saturday
  if(daysBackToSat < 7)
   daysBackToSat += 7; //6+7
 
  //Subtracting 13 Days for Last Saturday 
  //Since this Saturday is not Over
  cal.add(Calendar.DATE, daysBackToSat * -1);
  System.out.println("Start Date" + sdf.format(cal.getTime()));

  cal.add(Calendar.DATE, 6);
  System.out.println("End Date" + sdf.format(cal.getTime()));

Output Code
2013-06-15
2013-06-21