Stream filter() in Java with examples

Syntax:

Stream<T> filter(Predicate<? super T> predicate)

Returns a stream consisting of the elements of this stream that match the given predicate.

To see how filter() works, let’s create a Player class:

public class Player {

    private String name;
    private int points;
    private boolean vip;
    //Constructor and standard getters

and create some data to play with:

Player peter = new Player("Peter Parker", 15, false);
Player sarah = new Player("Sarah Johnes", 200, true);
Player charles = new Player("Charles Chaplin", 150, false);
Player mary = new Player("Mary Poppins", 1, true);

List<Player> players = Arrays.asList(peter, sarah, charles, mary);

So, for example if we want to see only VIP players, before Java 8 our filter of players would looks like:

List<Player> vipPlayersJava7 = new ArrayList<>();
for (Player p : players) {
    if (p.isVip()) {
        vipPlayersJava7.add(p);
    }
}

How this can be done with Java 8 ? It is just a matter of single line as follows.

List<Player> vipPlayersJava8 = players.stream()
.filter(v -> v.isVip())
.collect(Collectors.toList());

We have passed a Predicate instance into the filter() method in the form of a Lambda expression.

We can also use a method reference, which is shorthand for a lambda expression:

List<Player> vipPlayerJava8MethodRef = players.stream()
        .filter(Player::isVip)
        .collect(Collectors.toList());

Also, we can use multiple conditions with filter(). For example, filter by VIP status and name:

List<Player> sarahAndVip = players.stream()
        .filter(p -> p.getName().startsWith("Sarah") && p.isVip())
        .collect(Collectors.toList());

Interface Segregation Principle

Clients should not be forced to depend upon interfaces that they do not use.

  • Make fine grained interfaces that are client specific
  • Many client specific interfaces are better than one “general purpose” interface
  • Keep your components focused and minimize dependencies between them
  • Notice relationship to the Single Responsibility Principle?
  • avoid ‘god’ interfaces

Liskov Subsitution Principle

If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction.

  • By Barbara Liskov, in 1998
  • Objects in a program would be replaceable with instances of their subtypes WITHOUT altering the correctness of the program.
  • Violations will often fail the “Is a” test.
  • A Square “Is a” Rectangle
  • However, a Rectangle “Is Not” a Square

Open/Closed Principle

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

  • Your classes should be open for extension
  • But closed for modification
  • You should be able to extend a classes behavior, without modifying it.
  • Use private variables with getters and setters – ONLY when you need them.
  • Use abstract base classes

Difference between HashMap and HashSet in Java

HashSet

  1. HashSet class implements the Set interface
  2. In HashSet, we store objects(elements or values) e.g. If we have a HashSet of string elements then it could depict a set of HashSet elements: {“Hello”, “Hi”, “Bye”, “Run”}
  3. HashSet does not allow duplicate elements that mean you can not store duplicate values in HashSet.
  4. HashSet permits to have a single null value.
  5. HashSet is not synchronized which means they are not suitable for thread-safe operations until unless synchronized explicitly.[similarity]

HashSet example:

import java.util.HashSet;
class HashSetDemo{ 
  public static void main(String[] args) {
     // Create a HashSet
     HashSet<String> hset = new HashSet<String>();
 
     //add elements to HashSet
     hset.add("AA");
     hset.add("BB");
     hset.add("CC");
     hset.add("DD");
 
     // Displaying HashSet elements
     System.out.println("HashSet contains: ");
     for(String temp : hset){
        System.out.println(temp);
     }
  }
}

HashSet contains: 
AA
BB
CC
DD

 

HashMap

  1. HashMap class implements the Map interface
  2. HashMap is used for storing key & value pairs. In short, it maintains the mapping of key & value (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This is how you could represent HashMap elements if it has integer key and value of String type: e.g. {1->”Hello”, 2->”Hi”, 3->”Bye”, 4->”Run”}
  3. HashMap does not allow duplicate keys however it allows having duplicate values.
  4. HashMap permits single null key and any number of null values.
  5. HashMap is not synchronized which means they are not suitable for thread-safe operations until unless synchronized explicitly.[similarity]

HashMap example:

import java.util.HashMap;
class HashMapDemo{ 
  public static void main(String[] args) {
     // Create a HashMap
     HashMap<Integer, String> hmap = new HashMap<Integer, String>();
 
     //add elements to HashMap
     hmap.put(1, "AA");
     hmap.put(2, "BB");
     hmap.put(3, "CC");
     hmap.put(4, "DD");
 
     // Displaying HashMap elements
     System.out.println("HashMap contains: "+hmap);
  }
}

HashMap contains: {1=AA, 2=BB, 3=CC, 4=DD}

 

Difference between HashSet and HashMap in Java

HashMap Hash Set
HashMap  is an implementation of Map interface HashSet is an implementation of Set Interface
HashMap Stores data in form of  key-value pair HashSet Store only objects
Put method is used to add element in map Add method is used to add element is Set
In hash map hashcode value is calculated using key object Here member object is used for calculating hashcode value which can be same for two objects so equal () method is used to check for equality if it returns false that means two objects are different.
HashMap is faster than HashSet because unique key is used to access object HashSet is slower than Hashmap

 

NoClassDefFoundError vs ClassNotFoundException

ClassNotFoundException and NoClassDefFoundError occur when a particular class is not found at runtime. However, they occur at different scenarios.

NoClassDefFoundError:

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.

The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.

ClassNotFoundException:

Thrown when an application tries to load in a class through its string name using:

  • The forName method in class Class.
  • The findSystemClass method in class ClassLoader.
  • The loadClass method in class ClassLoader.

but no definition for the class with the specified name could be found. For example, you may have come across this exception when you try to connect to MySQL or Oracle databases and you have not updated the classpath with required JAR files. Most of the time, this exception occurs when you try to run an application without updating the classpath with required JAR files.

ClassNotFoundException NoClassDefFoundError
It is an exception. It is of type java.lang.Exception. It is an error. It is of type java.lang.Error.
It occurs when an application tries to load a class at run time which is not updated in the classpath. It occurs when java runtime system doesn’t find a class definition, which is present at compile time, but missing at run time.
It is thrown by the application itself. It is thrown by the methods like Class.forName(), loadClass() and findSystemClass(). It is thrown by the Java Runtime System.
It occurs when classpath is not updated with required JAR files. It occurs when required class definition is missing at runtime.

 

 

Default Methods in Java 8

In this article, I’ll try to explain what are default methods in Java 8, why they are useful and how they can be used to enhance the design of your code.

Default methods are added to Java 8 largely to support library designers by enabling them to write more evolvable interfaces. Java 8 introduces “Default Method” or (Defender methods) new feature, which allows developers to add new methods to the interfaces without breaking the existing implementation of these interfaces. Default methods are non-abstract and marked by the modifier default. It provides flexibility to allow the interface define implementation which will use as default in the situation where a concrete class fails to provide an implementation for that method.

Let’s consider this piece of code to understand how it works, in this example, I’ve just added a new default method newDefaultMethod() to the existing ‘old’ interface.

/**
 * Created by marom on 20/11/16.
 */
public interface SomeOldInterface {

    public void existingMethod();

    default public void newDefaultMethod() {

        System.out.println("New default method is added in the interface");

    }
}

An existing implementation of that interface will successfully compile without errors.

/**
 * Created by marom on 20/11/16.
 */
public class SomeOldInterfaceImpl implements SomeOldInterface {

    public void existingMethod() {
        // existing implementation is here…
    }
}

 

Why Default Method?

Reengineering an existing JDK framework is always very complex. Modify one interface in JDK framework breaks all classes that extends the interface which means that adding any new method could break millions of lines of code. Therefore, default methods have introduced as a mechanism to extending interfaces in a backwards compatible way.

Default methods can be provided to an interface without affecting implementing classes as it includes an implementation. If each added method in an interface defined with implementation then no implementing class is affected. An implementing class can override the default implementation provided by the interface.

For Java 8, the JDK collections have been extended and forEach method is added to the entire collection (which work in conjunction with lambdas).

public interface Iterable<T> {
public default void forEach(Consumer<? super T> consumer) {
    for (T t : this) {
        consumer.accept(t);
    }
  }
}

The same mechanism has been used to add Stream in JDK interface without breaking the implementing classes.

When to Use Default Method Over Abstract Classes?

After introducing Default Method, it seems that interfaces and abstract classes are same. However, they are still a different concept in Java 8.

Abstract classes can still do more in comparison to Java 8 interfaces:

  • An abstract class can have a constructor.
  • Abstract classes are more structured and can hold a state.

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation.

However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.

With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.

Conceptually, the main purpose of defender methods is a backwards compatibility after an introduction of new features (as lambda functions) in Java 8.

Are the abstract classes still useful in that scenario?

Yes. They are still useful. They can contain non-static, non-final methods and attributes (protected, private in addition to public), which is not possible even with Java-8 interfaces.

Default Method and Multiple Inheritance Ambiguity Problems.

Since java class can implement multiple interfaces and each interface can define default method with same method signature, therefore, the inherited methods can conflict with each other.

Let’s check this example:

/**
 * Created by marom on 20/11/16.
 */
public interface InterfaceA {

    default void defaultMethod() {

        System.out.println("Interface A default method");

    }
}
/**
 * Created by marom on 20/11/16.
 */
public interface InterfaceB {

    default void defaultMethod() {

        System.out.println("Interface B default method");

    }
}
/**
 * Created by marom on 20/11/16.
 */
public class InterfaceABImpl implements InterfaceA, InterfaceB {

}

The above code will fail to compile with the following error:

java: class Impl inherits unrelated defaults for defaultMethod() from types InterfaceA and InterfaceB

In order to fix this class, we need to provide default method implementation:

/**
 * Created by marom on 20/11/16.
 */
public class InterfaceABImpl implements InterfaceA, InterfaceB {

    public void defaultMethod() {
        // default method implementation
    }
}

Further, if we want to invoke default implementation provided by any of super interface rather than our own implementation, we can do so as follows:

/**
 * Created by marom on 20/11/16.
 */
public class InterfaceABImpl implements InterfaceA, InterfaceB {

    public void defaultMethod() {
        // default method implementation
        InterfaceA.super.defaultMethod();
    }
}

 

Difference Between Default Method and Regular Method

Default Method is different from the regular method in the sense that default method comes with default modifier. Additionally, methods in classes can use and modify method arguments as well as the fields of their class but default method, on the other hand, can only access its arguments as interfaces do not have any state.

 

In summary, Default methods enable to add new functionality to existing interfaces without breaking older implementation of these interfaces.

When we extend an interface that contains a default method, we can perform following,

  • Not override the default method and will inherit the default method.
  • Override the default method similar to other methods we override in a subclass.
  • Redeclare default method as abstract, which force a subclass to override it.

JUnit – assertThat (Hamcrest) – part 3

Ok, it’s time to continue our series of examples Hamcrest matchers usage. Previous blog posts can be found here (part 1part 2).

  • endsWith()

Creates a matcher that matches if the examined String ends with the specified String.

   @Test
    public void endsWithExample() {

        assertThat("Let's test endsWith matcher", endsWith("matcher"));
    }

 

  • equalTo()

Creates a matcher that matches when the examined object is logically equal to the examined object.

   @Test
    public void equalToValueExample() {

        String testValue = "text";

        assertThat(testValue, equalTo("text"));
    }

 

equalTo() can also be used on Arrays in which case it will check the length of the Array and ensure that all the values in the input test array are logically equal to the values of the specified array.

   @Test
    public void equalToArrayExample() {

        assertThat(new String[] {"Jon", "Paul"}, equalTo(new String[] {"Jon", "Paul"}));
    }

 

  • equalToIgnoringCase()

Creates a matcher of String that matches when the examined string is equal to the specified expectedString, ignoring case.

   @Test
    public void equalToIgnoringCaseExample() {

        String testValue = "TeXt";

        assertThat("text", equalToIgnoringCase(testValue));
    }

 

  • equalToIgnoringWhiteSpace()

Creates a matcher of String that matches when the examined string is equal to the specified expected String when whitespace differences are (mostly) ignored. To be exact, the following whitespace rules are applied:

  1. all leading and trailing whitespace of both the expected String and the examined string are ignored
  2. any remaining whitespace, appearing within either string, is collapsed to a single space before comparison
   @Test
    public void equalToIgnoringWhiteSpaceExample() {

        String testValue = "all leading    and trailing whitespace of both    the       expectedString and     the examined string   are       ignored    ";

        // Then
        assertThat(testValue, equalToIgnoringWhiteSpace("all leading and trailing whitespace of both the expectedString and the examined string are ignored"));
    }

 

  • greaterThan()

Creates a matcher of Comparable object that matches when the examined object is greater than the specified value, as reported by the compareTo method of the examined object.

   @Test
    public void greaterThanExample() {

        Integer testValue = 5;

        assertThat(6, is(greaterThan(testValue)));
    }

 

  • greaterThanOrEqualTo()

Creates a matcher of Comparable object that matches when the examined object is greater than or equal to the specified value, as reported by the compareTo method of the examined object.

    @Test
    public void greaterThanOrEqualToExample() {

        Double testValue = 5.5;

        assertThat(5.5, is(greaterThanOrEqualTo(testValue)));
    }

 

  • hasEntry()

Creates a matcher for Maps matching when the examined Map contains at least one entry whose key equals the specified key and whose value equals the specified value.

  @Test
    public void hasEntryExample() {

        Map<Integer, String> myMap = new HashMap<>();
        myMap.put(1, "value");

        assertThat(myMap, hasEntry(1, "value"));
    }

 

  • hasKey()

Creates a matcher for Maps matching when the examined Map contains at least one key that satisfies the specified matcher.

  @Test
    public void hasKeyExample() {

        Map<Integer, String> myMap = new HashMap<>();
        myMap.put(1, "value");
        myMap.put(2, "anotherValue");

        assertThat(myMap, hasKey(1));

 

  • hasValue()

Creates a matcher for Maps matching when the examined Map contains at least one value that is equal to the specified value.

   @Test
    public void hasValueExample() {

        Map<Integer, String> myMap = new HashMap<>();
        myMap.put(1, "value");
        myMap.put(2, "anotherValue");

        assertThat(myMap, hasValue("anotherValue"));
    }

 

  • hasItem()

Creates a matcher for Iterables that only matches when a single pass over the examined Iterable yields at least one item that is equal to the specified item. Whilst matching, the traversal of the examined Iterable will stop as soon as a matching item is found.

   @Test
    public void hasItemExample() {

        List<Integer> testList = Arrays.asList(50, 60, 4, 67, 9);

        assertThat(testList, hasItem(67));

    }

 

  • hasItems()

Creates a matcher for Iterables that matches when consecutive passes over the examined Iterable yield at least one item that is equal to the corresponding item from the specified items. Whilst matching, each traversal of the examined Iterable will stop as soon as a matching item is found.

    @Test
    public void hasItemsExample() {

        List<Integer> testList = Arrays.asList(50, 60, 4, 67, 9);

        assertThat(testList, hasItems(67, 60));
    }

 

  • hasSize()

Creates a matcher for Collections that matches when the size() method returns a value equal to the specified size.

   @Test
    public void hasSizeExample() {

        List<Integer> testList = Arrays.asList(50, 60, 4, 67, 9);

        assertThat(testList, hasSize(5));
    }

 

  • instanceOf()

Creates a matcher that matches when the examined object is an instance of the specified type.

   @Test
    public void instanceOfExample() {

        Object integer = 5;

        assertThat(integer, instanceOf(Integer.class));
    }

 

 

JUnit – assertThat (Hamcrest) – part 2

Let’s continue (you can find Hamcrest matchers – part 1 here) our series of examples how to write JUnit test with Hamcrest matchers usage.

  • comparesEqualTo()

Creates a matcher of a Comparable object that matches when the examined object is equal to the specified value, as reported by the compareTo method of the examined object. The value which, when passed to the compareTo method of the examined object, should return zero.

   @Test
    public void comparesEqualToExample() {

        assertThat(5, comparesEqualTo(5));
    }

 

  • contains()

Various matchers which can be used to check if an input Iterable contains values. The order of the values is important and the number of items in the Iterable must match the number of values being tested.

Test if the input list contains all of the values, the order of items is important.

  @Test
    public void containsItemsExample() {
        // Given
        List<String> names = Arrays.asList("Jon", "Peter", "Paul");

        // Then
        assertThat(names, contains("Jon", "Peter", "Paul"));
    }

Test if the input list contains items which match all of the matchers in the input matchers list, the order of items is important.

   @Test
    public void containsAllMatchersExample() {
        // Given
        List<String> strings = Arrays.asList("Jon", "Peter", "Paul");

        // Then
        List<org.hamcrest.Matcher<? super String>> matchers = new ArrayList<>();
        matchers.add(startsWith("Jo"));
        matchers.add(endsWith("ter"));
        matchers.add(equalTo("Paul"));
        assertThat(strings, contains(matchers));
    }

 

  • containsInAnyOrder()

This one is like contains() but as the name suggest the order of items is not important.

   @Test
    public void containsItemsInAnyOrderExample() {
        // Given
        List<String> names = Arrays.asList("Jon", "Peter", "Paul");

        // Then
        assertThat(names, containsInAnyOrder("Peter", "Jon", "Paul"));
    }

   @Test
    public void containsAllMatchersInAnyOrderExample() {
        // Given
        List<String> strings = Arrays.asList("Jon", "Peter", "Paul");

        // Then
        List<org.hamcrest.Matcher<? super String>> matchers = new ArrayList<>();
        matchers.add(endsWith("ter"));
        matchers.add(startsWith("Jo"));
        matchers.add(equalTo("Paul"));
        assertThat(strings, containsInAnyOrder(matchers));
    }

 

  • containsString()

A matcher that matches if the examined String contains the specified String anywhere.

   @Test
    public void containsStringExample() {
        // Given
        String testValue = "A very short sentence.";

        // Then
        assertThat(testValue, containsString("nt"));
    }

 

  • empty()

A matcher for Collections matching examined collections whose isEmpty method returns true.

    @Test
    public void emptyMatcherExample() {
        // Given
        Queue<String> collectionToTest = new LinkedList<>();

        // Then
        assertThat(collectionToTest, is(empty()));
    }

 

  • emptyArray()

A matcher for arrays that matches when the length of the array is zero.

   @Test
    public void emptyArrayMatcherExample() {
        // Given
        Integer[] arrayToTest = new Integer[0];

        // Then
        assertThat(arrayToTest, is(emptyArray()));
    }

 

  • emptyCollectionOf()

A matcher for Collections matching examined collections whose isEmpty method returns true.

   @Test
    public void emptyCollectionOfMatcherExample() {
        // Given
        Set<String> collectionToTest = new HashSet<>();

        // Then
        assertThat(collectionToTest, is(emptyCollectionOf(String.class)));
    }

 

  • emptyIterable()

A matcher for Iterables matching examined iterable that yield no items.

  @Test
    public void emptyIterableMatcherExample() throws Exception {
        // Given
        ArrayList<String> collectionToTest = new ArrayList<>();

        // Then
        assertThat(collectionToTest, is(emptyIterable()));
    }

 

  • emptyIterableOf()

A matcher for Iterables matching examined iterable that yield no items and is of the given type.

   @Test
    public void emptyIterableOfMatcherExample() throws Exception {
        // Given
        ArrayList<String> collectionToTest = new ArrayList<>();

        // Then
        assertThat(collectionToTest, is(emptyIterableOf(String.class)));
    }