Category Archives: Java

Java Collection Framework and Generics

As the name suggests, a Java Collection is a collection of objects represented as a single unit. The idea is to provide a set of operations on the logically grouped elements like searching, sorting, etc.

collection framework hierarchy
source: https://techvidvan.com/tutorials/java-collection-framework/

As the image above shows, there are two core interfaces, Collection and Map. The collection further has interfaces for List, Queue, and Set. For each of these interfaces than we have a concrete set of classes implementing the functionality.

Let’s take a very simple example

Collection values = new ArrayList();
values.add(1);
values.add(2);
values.add("kamal");

We can see collection interface helps us create a new ArrayList, which gives us flexibility over the array where the List can grow during runtime.

But one challenge we can see in the code above is that when we are able to add numbers as well as String to the ArrayList. This is in contrast with the type safety provided by Java. To solve this Java provides us Generics to control over types of elements that can be added to a collection.

Generics Example

class MyClass<T>{
T value;

public T getValue() {
return value;
}

public void setValue(T value) {
this.value = value;
}
}

Coming to our previous code for creating collections

Collection<Integer> values = new ArrayList<>();
values.add(1);

In this example, we cannot add a String to values now.

What if we want to get or add into ArrayList at a particular index. List Interface adds these features on top of Collection. As already depicted in the hierarchy, List inherits Collection and then adds features on top of it.

List<Integer> values = new ArrayList<>();
values.add(1);
int num = values.get(0);

Iterating over a Collection

There are multiple ways to iterate over a collection

List<Integer> values = new ArrayList<>();
values.add(1);
values.add(2);
values.add(3);
Iterator<Integer> i= values.iterator();
while(i.hasNext()) {
    System.out.println(i.next());
}

Another way is to use for loop

for(Integer num:values) {
   System.out.println(num);
}

Or we can use Streams

values.stream().forEach(System.out::println)

Comparable vs Comparator

Another important thing one would like to do with the collection is to arrange elements in sorted order. For example, say we have a List created for Student class objects, and we want to arrange based on Roll numbers.

The easiest way is to make the class implement comparable

class Student implements Comparable<Student>{

 int rollno;
 String name;

 public Student(int rollno, String name) {
  this.rollno=rollno;
  this.name=name;
 }

 @Override
 public int compareTo(Student o) {
  return this.rollno<o.rollno?-1 : (this.rollno==o.rollno)?0:1;
 }
}

// In calling code, we can sort list made up of students 
Collections.sort(list);

There can be cases where it is handy to maintain comparison based on multiple criteria. For example, along with roll number, we want to make sure we can sort the list of students based on names in alphabetical order. In such a case it makes sense to implement Comparator as we can implement multiple comparators based on our need.

class NameComparator implements Comparator<Student>{
 @Override
 public int compare(Student o1, Student o2) {
  return o1.name.compareTo(o2.name);
 }
}

// In calling code, we will send compatator instance 
Collections.sort(list, new NameComparator());

Getting started with Spring Boot

This is a short tutorial about creating a simple REST webservice with spring boot. This assumes you have basic knowledge of Spring and Java.

To get started we will create a Spring project. The simplest way to do this is to go to http://start.spring.io/ and create a project.

This will give us a blank project on which we can build upon. Import the project as Maven project to Eclipse or any other ID. By default, it will provide a class which will look like

@SpringBootApplication
public class NewtestApplication {

	public static void main(String[] args) {
		SpringApplication.run(NewtestApplication.class, args);
	}
}

As you can see this is the main class and all the execution starts here. Also, note the @SpringBootApplication annotation. Spring documentation states that

“The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes”

For this example, we will keep it simple and introduce a controller

@RestController
public class HelloController {
	
	@GetMapping("/sayhello")
	public String sayHello() {
		return("Hello");
	}
}

Finally, Run the main class as a normal Java application, it will automatically start the Spring Boot server at 8080.

We can now access our application at http://localhost:8080/sayhello

Updating Java version in Linux

Recently I upgraded my Java version from 9 to 10 on a Linux machine. I was able to set JAVA_Home in .bashrc file properly but version did not get updated when checked java -version on shell.

Following commands helped to change the system’s Java version

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/java" 1

And then

sudo update-alternatives --config java

This showed all the Java versions available and I was able to choose correct version i.e. 10.
Similary executed same commands for java compiler.

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/javac" 1
sudo update-alternatives --config javac

Features in Java 9

Java 9 might not be adding major changes like Java 8 which had features like Lambda or Streams or Interface modification, but it does have some good additions.

JShell: If you have worked in python or ruby, you might be aware of shell features these languages provide to quickly run and analyze commands and snippets. Java has come up with similar shell as JShell in Java 9 where you can evaluate the system.

Java Modules/ Jigsaw: Java has taken further step towards modularization. You can define your application in forms of modules and tell JVM what all modules will be used by current module, and what all modules will be exposed which can be used by others.

Private Methods in Interfaces: Java 8 gave us liberty to add method definitions in form of static and default implementations. With Java 9, one can add private methods to help us with organising our code better.

Additional Reads

http://www.baeldung.com/new-java-9
https://www.pluralsight.com/blog/software-development/java-9-new-features

Features added in Java 8

I have already talked about 2 most important features added in Java 8 in my last posts, i.e. Lambda and Streams. Apart from these there were few interesting additions.

Method definition in interfaces: For long time, Java has avoided multiple inheritance due to dreaded diamond problem. They had given us interfaces which did not had method definition, which could have been implemented by a class in multiple numbers. Now, Java has relieved the restriction a bit by allowing static and default methods definition in interfaces.
What about multiple inheritance diamond problem? Well if compiler cannot decide which implementation to use it will thrown an exception.

ForEach: For Collections like Lists, instead of creating an explicit iterator one can use forEach.

Optional: There can be a situation when a method can return null, in such situations the value can be saved in optional class.

Good reads: https://www.journaldev.com/2389/java-8-features-with-examples
http://www.baeldung.com/java-8-new-features

Lambda expressions in Java

Lambda expressions in java is a way to implement functional interfaces. Functional interface is the one which only has single unimplemented method. This gives us freedom from creating a class or anonymous class. In addition Lambdas can be used with streams.

Here is an example. Download the code here

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Jaba8Lambda {

	interface Operations{
		public int operate(int a, int b);
	}
	
	public static void main(String s[]) {
		System.out.println("Welcome to Lambdas");
		
		// A simplest form of lambda, same interface, multiple implementations without a class
		Operations sum = (int a, int b)->a+b;
		Operations multiple = (int a, int b)->a*b;
		
		//Java8Lambda obj= new Jaba8Lambda();
		int mysum = sum.operate(2, 3);
		System.out.println(mysum);
		int myproduct = multiple.operate(2, 3);
		System.out.println(myproduct);
		
		// Another example using Thread Runnable
		// Earlier you would create a Runnable
		
		Runnable myrun = new Runnable() {
			
			@Override
			public void run() {
				System.out.println("starting:"+Thread.currentThread().getName());
			}
		};
		
		new Thread(myrun).start();
		
		// With Labdas we can do away with anonymous classes
		Runnable myrunLambda = ()->{
			System.out.println("starting:"+Thread.currentThread().getName());
		};
		new Thread(myrunLambda).start();
		
		// Lambdas can be used with streams as well
		List intlist= new ArrayList();
		intlist.add(2);
		intlist.add(7);
		intlist.add(12);
		intlist.add(17);
		Stream stream = intlist.stream(); 
		stream.forEach(i->{
			if(i%2==0) {
				System.out.println(i+" is even.");
			}
		});

	}
}

Java Streams

Java had introduced streams in Java 8 to help us fasten the development by providing ways to perform operations on data streams (collections) without writing bulky code.

In short, stream can be thought of stream or pipeline of data, on which you need to perform some operations. There can be two types of operations, intermediate and terminal. Intermediate operations are the ones which transforms the data in the stream, but the output is still a stream, for example filter or map operations. On the other hand terminal operations are ones which are applied collectively on the stream and output is something other than stream for example sum or reduce methods.

Here is an example usage to make it more clear. Or Download code from git repo

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Java8Streams {
	
	public static void main(String s[]) {
		System.out.println("Welcome to streams!");
		
		//There are multiple ways to create streams
		Stream stream = Stream.of(new Integer[]{1,2,3,4}); 
		Stream intStream = Stream.of(1,2,3,4);


		// Using streams to find sum of a integer list
		List intlist= new ArrayList();
		intlist.add(2);
		intlist.add(7);
		intlist.add(12);
		intlist.add(17);
		Stream streamnew = intlist.stream(); 
		
		// No more looping through the array
		Integer sum = intlist.stream().mapToInt(i->i).sum();
		System.out.println("Sum is :"+sum);
		
		// Lets check if the array contains even number, without looping
		boolean anyEven= intlist.stream().anyMatch(i->i%2==0);
		System.out.println(anyEven);
		
		// Check if all elements are even in the list
		boolean allEven = intlist.stream().allMatch(i->i%2==0);
		System.out.println(allEven);
		
		// Find first even number from the list
		Optional firsteven= intlist.stream().filter(i->i%2==0).findFirst();
		System.out.println(firsteven);
		
		// Now lets sum all even numbers
		int sumeven = intlist.stream().filter(i->i%2==0).mapToInt(i->i).sum();
		System.out.println(sumeven);
		
		// Lets use forEach to do operations on each element, say add a constant number to even numbers and print
		intlist.stream().forEach(i->{
			if(i%2==0) {
				i = i+100;
				System.out.print(i+",");
			}
		});
		System.out.println();
		//Better way to achieve the above
		intlist.stream().filter(i->i%2==0).forEach(i->{
			i = i+100;
			System.out.print(i+",");
		});
		
		System.out.println();
		// Simliar to filter, we gave map function
		List newlist = intlist.stream().map(i->{
			return i+100;
		}).collect(Collectors.toList());
		System.out.println(newlist);
		
		// Use reduce to perform some custom operation
		Optional output = intlist.stream().map(i->{
			return i+10;
		}).reduce((i,j)->{
			return i*j;
		});
		System.out.println(output);
		
	}

}

Java- Call by Reference vs Call by Value

In Java, when we send objects to a method, do they get passed by reference or by value?
Answer is, the reference of object is passed by value. This can be a bit tricky to absorb first. Let us try to understand. Reference in this case is a pointer (just to visualize, as we know there are no pointers in Java) to the object location.

Employee obj = new Employee();
sendToMethod(obj);

When we are sending this obj to a method, the object copy itself does not get sent neither the object reference. It is the copy of obj reference. So think of it like obj is stored at location “HB10”, this “HB10” gets copied and sent to method. Any changes directly made to the object gets reflected back to the calling method, but if reference itself is update, no changes get reflected.

private void sendToMethod(Employee obj)
{
obj.setSalary(100000);// gets reflected
obj = new Exployee(); // we removed reference, so no changes after this will be reflected in calling method.
obj.setDept(“IT”);// does not gets reflected.
}

A more elaborated example code

import java.util.ArrayList;

public class Test {

public static void main(String args[]) {
ArrayList iList = new ArrayList();
iList.add(1);
System.out.println(“\nPrint list Before”);
iList.stream().forEach(x->System.out.print(x+”, “)); // prints 1,
updateMe(iList);
System.out.println(“\nPrint list After”);
iList.stream().forEach(x->System.out.print(x+”, “)); // prints 1, 2,
}
public static void updateMe(ArrayList iList) {
ArrayList jList = new ArrayList();
iList.add(2); //this gets reflected
jList.add(3);
iList = jList; // reference changed, no changes after this are reflected.
iList.add(4);
jList.add(5);
}
}

Node vs Java Comparison

A good read on Node vs Java https://rclayton.silvrback.com/speaking-intelligently-about-java-vs-node-performance. Explains about the way Java and Node code will work to handle load.

My personal opinion is that programming language is just a tool to deliver the final solution. Only in specialized cases, where we know that a particular language has proven history of solving similar kind of problems, hence has sample code, libraries, knowledge base, forums to help, we should consider that as part of solution. Otherwise non-technical reasons like client preferences, team’e expertise will come into picture.