Skip to main content

Java

  • what is java

    • a simple language
      • derives its syntax from C++
      • takes care of memory management
      • it provides an automatic garbage collector
        • collects the unused objects automatically
    • a multithreaded language
      • Java can perform many tasks at once by defining multiple threads
        • For example, a program that manages a Graphical User Interface (GUI) while waiting for input from a network connection uses another thread to perform and wait instead of using the default GUI thread for both tasks, keeping the GUI responsive
    • can create applets
      • Applets are programs that run in web browsers
      • But applets support was deprecated in Java 9 release and has been removed in Java 11 release due to waning browser support for the Java plugin
    • object-oriented
      • OOP makes the complete program simpler by dividing it into a number of objects
      • The objects can be used as a bridge to have data flow from one function to another
      • We can easily modify data and functions as per the requirements of the program
    • does not require any preprocessor
      • It does not require inclusion of header files for creating a Java application
    • platform-independent
      • programs written after compilation, are converted into an intermediate level language called the bytecode
        • it is a part of the Java platform irrespective of the machine on which the programs run
        • Every Operating System has a different JVM
          • but the output they produce after the execution of bytecode is the same across all the operating systems
      • This makes java highly portable as its bytecodes can be run on any machine by an interpreter called the Java Virtual Machine (JVM) thus it provides ‘reusability of code’
        • How JVM works - JVM architecture
        • each java app executes within its own instance of the JVM
        • the operating system treats that JVM instance as a separate, independent process
        • thus if multiple java apps were run at the same time, they will each execute in a separate JVM process with their own independent memory space
        • have 3 execution phases of a program
          1. written
            • Writing a program is done by a java programmer like you and me
          2. compile
            • The compilation is done by the JAVAC compiler which is a primary Java compiler included in the Java development kit (JDK)
            • It takes the Java program as input and generates bytecode as output
              • so that it can be executed by JVM
              • It is saved as .class file by the compiler
              • To view the bytecode, a disassembler like javap can be used
          3. run
            • In the Running phase of a program, JVM executes the bytecode generated by the compiler
    • a robust language
      • Java programs must be reliable because they are used in both consumer and mission-critical applications, ranging from Blu-ray players to navigation systems
      • It is developed in such a way that it puts a lot of effort into checking errors as early as possible
        • that is why the java compiler is able to detect even those errors that are not easy to detect by another programming language
      • The main features of java that make it robust are garbage collection, Exception Handling, and memory allocation
  • Java Development Kit (JDK)

    JDK

    • it is a complete Java development kit that includes tools such as the compiler, Java Runtime Environment (JRE), java debuggers, java docs, Jar, etc.
    • For the program to execute in java, we need to install JDK on our computer in order to create, compile and run the java program
  • Java Runtime Environment (JRE)

    • JDK includes JRE
      • JRE installation on our computers allows the java program to run
        • however, we cannot compile it
      • it contains the parts of the Java libraries required to run Java programs and is intended for end-users
    • JRE includes a browser, JVM, applet supports, and plugins
      • For running the java program, a computer needs JRE
  • Differences between JDK, JRE and JVM

  • Garbage Collector

    • programmers can’t delete the objects
    • To delete or recollect that memory JVM has a program called Garbage Collector
      • Garbage Collectors can recollect the objects that are not referenced
      • Java makes the life of a programmer easy by handling memory management
        • However, programmers should be careful about their code whether they are using objects that have been used for a long time
          • Because Garbage cannot recover the memory of objects being referenced
  • ClassPath

    • it is the file path where the java runtime and Java compiler look for .class files to load
    • By default, JDK provides many libraries
    • to include external libraries they should be added to the class path
  • Primary/Main Features of Java

  • Java keywords

    • words in a language that are used for some internal process or represent some predefined actions
    • These words are not allowed to use as variable names or objects
    • abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while

Table of Contents

Compiled Language

Statically-typed Language: resolution of types, members, properties, methods are done at compile-time

trying to access a method that is not defined in an object when compiling the app will get an immediate error feedback

  • Java: compiled to bytecode then interpreted by Java virtual machine into machine code

    • Features

      • not compatible with other languages
      • calls to native functions go through Java Native Interface (JNI)
      • write once, run anywhere
      • runs in a protected Java Virtual Machine (JVM)
      • managed memory access
      • limited to single inheritance
      • class-based inheritance
    • Types

      • Java Platform, Standard Edition (SE)
        • Core language and Java Runtime Environment (JRE)
      • Java Platform, Enterprise Edition (EE)
        • Recommendation for industrial-strength web applications
      • Java Platform, Micro Edition (ME)
        • Microcontrollers, sensors, mobile devices, telephone sim cards
        • A subset of Java SE
      • Java FX
        • Desktop application framework (windows, mac, linux)
    • Automatic memory management

      • memory for objects are allocated automatically

      • local variables & function calls are stored in stack

      • objects & member variables are stored in heap

      • objects are retained in memory until dereferenced

      • object is eligible for collection when all references expire

        • when do references expire

          • variables local to methods or code blocks expire with scope

            void changeString() {
            String localVar = "Won't be around for long!";
            System.out.println("In function: " + localVar);
            }
          • explicitly dereference variables with null keyword

            void changeString() {
            String localVar = "Won't be around for long!";
            tempVar = null;
            }
      • when Java Virtual Machine runs out of memory for a newly requested object

        • the system throws OutOfMemoryError
        • Tips for managing memory
          • minimize the number of objects created
          • find out how much memory is available & is currently in used in the virtual machine
            • Runtime.maxMemory() & Runtime.totalMemory()
          • setting available memory
            • use command line options to manage amount of available heap memory
              • set initial heap size java -Xms256s HelloWord
              • set max heap size java -Xmx256m HelloWord
              • set heap size for new objects java -Xmn256n HelloWord
    • Java Garbage Collector

      • runs in its own thread
      • allocates & deallocates memory
      • can destroy dereferenced objects, but not required
      • garbage collection is managed by the Virtual Machine
      • cannot force garbage collection as it is an automatic process
        • Can run System methods to call garbage collection
          • Methods System.gc() & Runtime.gc() can request garbage collection
            • but there is no guarantee it will happen
    • Identifiers and Keywords

      • Keywords can't be used as class or other identifiers
      • class, method, field, and other names are identifiers
      • identifiers must start with alpha character or underscore
    • Identifier conventions

    • classes are always Pascal case class MyClass {}

    • methods and variables are Camel case void doSomething(String withThis) {}

    • constants are all uppercase public static final String FIRSTNAME="Myname";

      • final means once it has been set, it can't be changed

back to top

Hello World

  • java classes are typically organized into packages
    • package is a global unique string that usually starts with your domain name in reverse domain order
      • ensures globally unique identifiers (e.g.: Main)
        • if there are more than 1 class named Main in an app
          • can be distinguished by using the package
  • each source code file will contain 1 public class
  • public visible to all classes
  • protected visible to class they belong and any subclasses
  • private (most restricted): visible only to class they belong
  • static can be accessed without creating a class instance
  • final constant value, value cannot be changed
  • void means that the method doesn't return any value
package com.example;  // package declaration

// class declaration
public class HelloWorld {
// main method: always have the 3 keywords (public, static, void)
// must also receive an array of strings as an argument
// String []args: This is the argument passed to the main function which is an array of strings with the array name args
// One can choose their own flexible name but this name is used by many developers
public static void main(String[] args) {
// executable code
System.out.println("Hello World"); // adds new line after printing
System.out.print("Hello World"); // no new line is added after
}
}

back to top

Comments

// Single line comment

/*
multi-line comments
*/

/**
* javadoc <b>documentation comments</b> for classes, javadocs can be used to auto generate documentation documents for code commented with javadocs
*/

/**
* javadoc <b>comments</b> for methods with parameters - example main method
* @param args - an array of string values
*/

back to top

Print

System.out.println("Hello World");  // adds new line after printing
System.out.print("Hello World"); // no new line is added after
  • formatting
    • print format reference
    • s for strings
    • S for uppercase strings, it converts lowercase to uppercase
    • c for characters
    • C for uppercase characters
    • d for byte, short, int, long, and BigInteger
    • f for float and double
    • t for date/time values
      • time
        • T for time hh:mm:ss
        • H for hours
        • M for minutes
        • S for seconds
        • L for milliseconds
        • N for nanoseconds
        • p adds a.m./p.m. formatting
        • z prints out the time-zone offset
      • data
        • A prints out the full day of the week
        • d formats a two-digit day of the month
        • B is for the full month name
        • m formats a two-digit month
        • Y outputs a year in four digits
        • y outputs the last two digits of the year
    • n for line separator
    • b for boolean
// syntax
System.out.printf(format, arguments);
System.out.printf(locale, format, arguments);

// example
System.out.printf("Hello %s!%n", "World"); // Hello World!

// add left spaces
System.out.printf("'%15s' %n", "baeldung"); // ' baeldung'

// add right spaces
System.out.printf("'%-10s' %n", "baeldung"); // 'baeldung '

// limit number of characters in string
/*
%x.ys syntax
x is the padding, y is the number of chars
*/
System.out.printf("%2.2s", "Hi there!"); // 'Hi'


// control float precision
/*
%x.yf syntax
x is the padding, y is the number of decimal places
*/
System.out.printf("'%5.2f'%n", 5.1473); // ' 5.15'

// using locale to format numbers
import java.util.Locale;
System.out.printf(Locale.US, "%,d %n", 10000); // 10,000
System.out.printf(Locale.ITALY, "%,d %n", 10000); // 10.000

// dates
import java.util.Date;
System.out.printf("%tT%n", date); // 13:51:15
System.out.printf("hours %tH: minutes %tM: seconds %tS%n", date, date, date); // hours 13: minutes 51: seconds 15

// extracting from 1 argument
System.out.printf("hours %1$tH: minutes %1$tM: seconds %1$tS%n", date); // hours 13: minutes 51: seconds 15

// date words format
System.out.printf("%1$tA, %1$tB %1$tY %n", date); // Thursday, November 2018

// date numeric format
System.out.printf("%1$td.%1$tm.%1$ty %n", date); // 22.11.18

back to top

Data types

java 8

data types

2 major data types

  1. Primitive data types

    primitive data types

    • stored in fastest available memory

    • names are all camel case

    • Java class library includes helper classes for each primitive

      • helper classes support conversion and formatting tools
      • import java.lang.Byte; import not required from java.lang libraries
    • all primitive numeric variables default to 0

      public class Main {
      private static int myInt; // must be declared as static of a class to have default value

      public static void main(String args[]) {
      System.out.println(myInt); // 0
      }
      }
    • data types

      • numbers

        • byte

          • 8 bits
          • -128 to 127
          • default value 0
          • helper class Byte
        • short

          • 16 bits
          • -32,768 to 32,767
          • default value 0
          • helper class Short
        • int

          • 32 bits
          • -2,147,483,648 to 2,147,483,647
          • default value 0
          • helper class Integer
          • from JAVA 8 onwards, it can be used to represent an unsigned 32-bit integer
        • long

          • 64 bits
          • -9.22337E+18 to 9.22337E+18
          • default value 0L
          • helper class Long
          • from JAVA 8 onwards, it can be used to represent an unsigned 64-bit long
        • float

          • 32 bits
          • up to 7 decimal digits
          • default value 0.0f or 0.0F or .0f or .0F
          • helper class Float
          • use BigDecimal class if accuracy is required
        • double

          • 64 bits
          • up to 16 decimal digits
          • default value 0.0d or 0.0D or .0d or .0D
          • helper class Double
          • use BigDecimal class if accuracy is required
          double doubleValue = 156.5d;
          Double doubleObj = new Double(doubleValue); // declare instance of the double class
          int intValue = doubleObj.intValue(); // 156, use helper object to convert to desired numeric data type
      • characters

        • 16 bits
        • \u0000 (or 0) to \uffff (or 65,535 inclusive)
        • default value \u0000
        • java uses the Unicode system and not the ASCII code system where 8 bits is enough
          • Unicode defines a fully international character set that can represent most of the world’s written languages
          • It is a unification of dozens of character sets, such as Latin, Greeks, Cyrillic, Katakana, Arabic, and many more
          • that's why 8 bits is not enough to represent all characters
      • booleans

        • default value false
  2. Non-primitive data type or Reference Data Types

    • it contain a memory address of variable values because the reference types won’t store the variable value directly in memory

    • String

      • a complex object
      • is an instance of the string class
      • is an array of characters
        • string is designed to hold a sequence of characters in a single variable
          • whereas, a character array is a collection of separate char type entities
        • Unlike C/C++, Java strings are not terminated with a null character
      • string objects are immutable
      • reassigning the string value creates a new object
        • the old object can be cleared from memory thrown garbage collection process
      • helper class is java.lang.String, thus import not required
      String string1 = new String("Hello");
    • Class

      • it is a user-defined blueprint or prototype from which objects are created

      • It represents the set of properties or methods that are common to all objects of one type

      • In general, class declarations can include these components, in order:

        • Modifiers A class can be public or has default access
        • Class name The name should begin with an initial letter (capitalized by convention)
        • Superclass The name of the class’s parent (superclass), if any, preceded by the keyword extends
          • A class can only extend (subclass) one parent
        • Interfaces A comma-separated list of interfaces implemented by the class, if any, preceded by the keyword implements
          • A class can implement more than one interface
        • Body The class body is surrounded by braces, { }
    • Object

      • It is a basic unit of Object-Oriented Programming and represents real-life entities
      • An object consists of
        • State It is represented by the attributes of an object
          • It also reflects the properties of an object
        • Behavior It is represented by the methods of an object
          • It also reflects the response of an object to other objects
        • Identity It gives a unique name to an object and enables one object to interact with other objects
    • Interface

      • it can have methods and variables, but the methods declared in an interface are by default abstract (only method signature, nobody)
      • Interfaces specify what a class must do and not how
        • It is the blueprint of the class
      • An Interface is about capabilities like a Player may be an interface and any class implementing Player must be able to (or must implement) a method called move
        • So it specifies a set of methods that the class has to implement
      • If a class implements an interface and does not provide method bodies for all functions specified in the interface, then the class must be declared abstract
      • A Java library example is Comparator Interface
        • If a class implements this interface, then it can be used to sort a collection
    • Array

      • An array is a group of like-typed variables that are referred to by a common name
      • Arrays in Java work differently than they do in C/C++. The following are some important points about Java arrays
        • In Java, all arrays are dynamically allocated
        • Since arrays are objects in Java, we can find their length using member length
          • This is different from C/C++ where we find length using size
        • A Java array variable can also be declared like other variables with [] after the data type
        • The variables in the array are ordered and each has an index beginning from 0
        • Java array can also be used as a static field, a local variable, or a method parameter
        • The size of an array must be specified by an int value and not long or short
        • The direct superclass of an array type is Object
        • Every array type implements the interfaces Cloneable and java.io.Serializable

back to top

Variable declaration

Variable declaration

Types of variables

  • also referred to as identifiers

  • Identifiers are the names of local variables, instance and class variables, and labels

    • it is also the names for classes, packages, modules and methods
    • All Unicode characters are valid, not just the ASCII subset
  • All identifiers can begin with a letter, a currency symbol or an underscore _

  • According to the convention, a letter should be lower case for variables

  • The first character of identifiers can be followed by any combination of letters, digits, currency symbols and the underscore

  • The underscore is not recommended for the names of variables

  • Constants (static final attributes and enums) should be in all Uppercase letters

  • identifiers are case-sensitive

  • A keyword cannot be used as an identifier since it is a reserved word and has some special meaning

  • example

    Legal identifiers: MinNumber, total, ak74, hello_world, $amount, _under_value
    Illegal identifiers: 74ak, -amount
  • multi variables declaration

    double num1, num2, num3;
  • type inference: starting from java 10

    • use var key word
    • type is derived from assigned value
    var myVar = 5;  // data type becomes integer
  • primitive numbers are always signed

  • long and integer methods support unsigned operations

    int unsigned = Integer.parseUnsignedInt("3000000000");
    System.out.println(unsigned); // -1294967296

    int result = Integer.divideUnsigned(unsigned, 2);
    System.out.println(result); // 1500000000

    int unsigned2 = Integer.parseUnsignedInt("300");
    System.out.println(unsigned2); // 300

    int result2 = Integer.divideUnsigned(unsigned2, 2);
    System.out.println(result2); // 150
  • if a variable has already been declared in the outer scope first, the same variable cannot be declared again in the inner scope

    class Test {
    public static void main(String args[]) {
    int a = 5;
    for (int a = 0; a < 5; a++) { // will raise an error that a is already defined
    System.out.println(a);
    }
    }
    }
  • if a variable was declared in the inner scope first before the same variable name was declared in the outer scope, it will work

    class Test {
    public static void main(String args[]) {
    for (int i = 1; i <= 10; i++) {
    System.out.println(i);
    }
    int i = 20;
    System.out.println(i);
    }
    }

back to top

Variable declaration int

  • integer ...-2, -1, 0, 1, 2...
// public/private/protected static final byte/short/int/long integerName = 123;

// byte: -128 ~ 127, 8 bits
// wrapper class: Byte
byte byteName = 123;

// short: -32768 ~ 32767, 16 bits
// wrapper class: Short
short shortName = 123;

// int: -2^31 ~ 2^31 - 1, -2147483648 ~ 2147483647, -2_147_483_648 ~ 2_147_483_647, 32 bits
// wrapper class: Integer
int integerName; integerName = 123;
int integerName2 = 123; // default is visible within the same package

// long: -2^63 ~ 2^63 - 1, -9223372036854775808L ~ 9223372036854775807L, can use _ same as int, 64 bits
// wrapper class: Long
long longName1 = 123l; // 123
long longName2 = 123L; // 123
long longName3 = 10_000; // 10000, introduced in java 7, just makes it easier to read

back to top

Variable declaration float

  • float, double
// float: 32 bits, 4 bytes
// wrapper class: Float
float float_name = 1.123f; // 1.123, have 7 decimal digits
float float_name = (float) 1.123;

// double: 64 bits, 8 bytes
// wrapper class: Double
double double_name = 1.123d; // 1.123, have 16 decimal digits
double double_name = 1.123;

// using BigDecimal math class
import java.math.BigDecimal;

public class Main {

public static void main(String[] args) {
double value = .012;
double pSum = value + value + value;
System.out.println(pSum); // 0.036000000000000004

String strValue = Double.toString(value);
System.out.println(strValue); // 0.012

BigDecimal bigValue1 = new BigDecimal(value);
BigDecimal bSum1 = bigValue1.add(bigValue1).add(bigValue1);
System.out.println(bSum1.toString()); // 0.0360000000000000007494005416219806647859513759613037109375

// convert double value to string for accuracy
BigDecimal bigValue2 = new BigDecimal(strValue);
BigDecimal bSum2 = bigValue2.add(bigValue2).add(bigValue2);
System.out.println(bSum2.toString()); // 0.036
}
}

back to top

Variable declaration None

String stringName = null;

// NaN is produced if a floating point operation
float floatName = Float.NaN; // NaN
double doubleName = Double.NaN; // NaN

Double x = new Double(-2.0/0.0); // -Infinity
Double y = new Double(0.0/0.0); // NaN
x.isNaN(); // false
y.isNaN(); // true

System.out.println(2.0 / 0); // Infinity

// set infinity value
double inf = Double.POSITIVE_INFINITY; // Infinity
double inf = Double.NEGATIVE_INFINITY; // -Infinity

back to top

Boolean

  • wrapper class: Boolean
boolean booleanName1 = true;
boolean booleanName2 = false;
boolean booleanName3 = !booleanName2; // true

String sBoolean = "true";
boolean booleanName4 = Boolean.parseBoolean(sBoolean); // true

back to top

Strings

  • characters

    // character: 16 bits, 2 bytes, only 1 letter or symbol, must use single quotes ''
    // wrapper class: Character
    char charName1 = 'a';
    char charName2 = '\u0061'; // unicode character for the letter a

    // modify character cases
    Character.toUpperCase(charName1); // 'A'
    Character.toLowerCase(charName1); // 'a'

    // convert Char Array to a string
    char[] chars = {'H', 'e', 'l', 'l', 'o'};
    String s = new String(chars); // "Hello"

    // convert string to char array
    char[] chars2 = s.toCharArray();
    for (char c : chars2) { // for each loop
    System.out.print(c); // "Hello"
    }
  • strings

    JVM Memory Area

    • Strings in Java are Objects that are backed internally by a char array
    • Since arrays are immutable(cannot grow), Strings are immutable as well
    • Whenever a change to a String is made, an entirely new String is created
    • memory allotment of string
      • Whenever a String Object is created as a literal, the object will be created in String constant pool
      • This allows JVM to optimize the initialization of String literal
    • The cache which stores these string instances is known as the String Constant pool or String Pool
      • In earlier versions of Java up to JDK 6 String pool was located inside PermGen(Permanent Generation) space
      • But in JDK 7 it is moved to the main heap area
        • Why did the String pool move from PermGen to the normal heap area?
          • PermGen space is limited, the default size is just 64 MB
          • it was a problem with creating and storing too many string objects in PermGen space
          • To make Java more memory efficient, the concept of string literal is used
          • By the use of the new keyword, The JVM will create a new string object in the normal heap area even if the same string object is present in the string pool
// convert primitive values to string
int intValue = 42;
String fromInt = Integer.toString(intValue); // "42"

boolean boolValue = true;
String fromBool = Boolean.toString(boolValue); // "true"


// strings: must use double quotes ""
String stringName = new String("Hello"); // method 1, dynamically allocated, assigned a new memory location in heap
// use "intern" method to store string in constant pool
String internedString = stringName.intern();

// this is preferred as it allows JVM to optimize memory allocation
String stringName1 = "string"; // method 2: string literal, created in String constant pool
String stringName2 = "multi-line " +
"string";


// get character of string with index
char charName = stringName1.charAt(0); // 's'

// get character code
int charCode = (int) charName; // 115

// get character code difference
System.out.println('b' - 'a'); // 98 - 97 = 1

// modify string cases
String stringName3 = stringName1.toUpperCase(); // "STRING"
String stringName4 = stringName3.toLowerCase(); // "string"


// get length of string
stringName4.length(); // 6

// Returns the index within the string of the first occurrence of the specified string
int index = stringName4.indexOf("ng"); // 4

// Returns the index within the string of the first occurrence of the specified string, starting at the specified index
String s = "Learn Share Learn";
int output = s.indexOf("ea", 3); // returns 13

// Returns the index within the string of the last occurrence of the specified string
int output = s.lastIndexOf("a"); // returns 14

// get substring with index
String sub1 = stringName4.substring(4); // "ng"
String sub2 = stringName4.substring(4, 6); // "ng" from starting index to but exclude last index

// trim whitespaces from beginning and ending of string
String trimStr = " test ";
String newStr = trimStr.trim(); // "test"


// Returns new string by replacing all occurrences of oldChar with newChar
String s1 = “feeksforfeeks“;
String s2 = “feeksforfeeks”.replace(‘f’ ,’g’); // returns “geeksgorgeeks”

// toString method: convert primitive numeric values to string
double doubleValue = .5d;
String stringName5 = Double.toString(doubleValue); // "0.5"


// comparing strings
String str1 = "Hello"; // object 1
String str2 = "Hello"; // str2 points to str1, thus is still object 1
str1 == str2; // true

String part1 = "Hello ";
String part2 = "World";
String str3 = part1 + part2; // object 1
String str4 = "Hello World"; // object 2
str3 == str4; // false
// need to use .equals()
str3.equals(str4); // true

// Compares string to another string, ignoring case considerations
str3.equalsIgnoreCase(str4);

// Compares two string lexicographically
/*
This returns difference s1-s2. If:
out < 0 // s1 comes before s2
out = 0 // s1 and s2 are equal.
out > 0 // s1 comes after s2.
*/
str3.compareTo(str4);

// Compares two string lexicographically, ignoring case considerations
str3.compareToIgnoreCase(str4);
  • StringTokenizer library

    • used to break a string into tokens
  • StringJoiner

    • a class in java.util package which is used to construct a sequence of characters(strings) separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix
  • string constructors

    • String(byte[] byte_arr) Construct a new String by decoding the byte array

      • uses the platform’s default character set for decoding
      byte[] b_arr = {71, 101, 101, 107, 115};
      String s_byte = new String(b_arr); // Geeks
    • String(byte[] byte_arr, Charset char_set) Construct a new String by decoding the byte array

      • It uses the char_set for decoding
      byte[] b_arr = {71, 101, 101, 107, 115};
      Charset cs = Charset.defaultCharset();
      String s_byte_char = new String(b_arr, cs); // Geeks
    • String(byte[] byte_arr, String char_set_name) Construct a new String by decoding the byte array

      • It uses the char_set_name for decoding
      byte[] b_arr = {71, 101, 101, 107, 115};
      String s = new String(b_arr, "US-ASCII"); // Geeks
    • String(byte[] byte_arr, int start_index, int length) Construct a new string from the bytes array depending on the start_index(Starting location) and length(number of characters from starting location)

      byte[] b_arr = {71, 101, 101, 107, 115};
      String s = new String(b_arr, 1, 3); // eek
    • String(byte[] byte_arr, int start_index, int length, Charset char_set) Construct a new string from the bytes array depending on the start_index(Starting location) and length(number of characters from starting location).Uses char_set for decoding

      byte[] b_arr = {71, 101, 101, 107, 115};
      Charset cs = Charset.defaultCharset();
      String s = new String(b_arr, 1, 3, cs); // eek
    • String(byte[] byte_arr, int start_index, int length, String char_set_name) Construct a new string from the bytes array depending on the start_index(Starting location) and length(number of characters from starting location).Uses char_set_name for decoding

      byte[] b_arr = {71, 101, 101, 107, 115};
      String s = new String(b_arr, 1, 4, "US-ASCII"); // eeks
    • String(char[] char_arr) Allocates a new String from the given Character array

      char char_arr[] = {'G', 'e', 'e', 'k', 's'};
      String s = new String(char_arr); //Geeks
      • String(char[] char_array, int start_index, int count) Allocates a String from a given character array but choose count characters from the start_index

        char char_arr[] = {'G', 'e', 'e', 'k', 's'};
        String s = new String(char_arr , 1, 3); //eek
      • String(int[] uni_code_points, int offset, int count) Allocates a String from a uni_code_array but choose count characters from the start_index

        int[] uni_code = {71, 101, 101, 107, 115};
        String s = new String(uni_code, 1, 3); //eek
      • String(StringBuffer s_buffer) Allocates a new string from the string in s_buffer

        StringBuffer s_buffer = new StringBuffer("Geeks");
        String s = new String(s_buffer); //Geeks
      • String(StringBuilder s_builder) Allocates a new string from the string in s_builder

        StringBuilder s_builder = new StringBuilder("Geeks");
        String s = new String(s_builder); //Geeks

back to top

String Concatenation

  • method 1

    String string1 = "string";
    int num1 = 1;

    String stringName1 = string1 + num1; // "string1"

    // method 2 (concat value must be string type)
    String newString1 = string1.concat(Integer.toString(num1)); // "string1"

    // method 3 (%s = string, %d = "byte, short, int, long, bigint", %c = char)
    String newString2 = String.format("%s%d", string1, num1); // "string1"
  • method 4: StringBuilder represents a mutable sequence of characters

    • it is not synchronized, which means that it is not thread-safe
    • The advantage of StringBuilder is faster performance
    String string1 = "string";
    int num1 = 1;

    StringBuilder sb1 = new StringBuilder(string1);
    sb1.append(num1); // "string1"
    // or
    StringBuilder sb2 = new StringBuilder();
    sb2.append(string1).append(num1); // "string1"
    // or
    StringBuilder sb3 = new StringBuilder(7);
    sb3.append("string");
    sb3.append(num1);

    sb2.delete(1, sb2.length()); // "s"
  • method 5: StringBuffer represents growable and writable character sequences

    • when using multithreading, must use StringBuffer rather than StringBuilder

      • because it is synchronized, thus is thread-safe
    • methods

      • append Used to add text at the end of the existing text
      • appendCodePoint appends the string representation of the codePoint argument to this sequence
      • length
      • capacity the total allocated capacity
      • charAt
      • delete Deletes a sequence of characters from the invoking object
      • deleteCharAt Deletes the character at the index specified by loc
      • ensureCapacity Ensures capacity is at least equals to the given minimum
      • insert Inserts text at the specified index position
      • reverse Reverse the characters within a StringBuffer object
      • replace Replace one set of characters with another set inside a StringBuffer object
    String string1 = "string";
    int num1 = 1;

    StringBuffer sBuffer1 = new StringBuffer(string1);
    sBuffer1.append(num1);
    sBuffer1.toString(); // "string1"
    // or
    StringBuffer sBuffer2 = new StringBuffer();
    sBuffer2.append(string1).append(num1);
    sBuffer2.toString(); // "string1"
    // or
    StringBuffer sBuffer3 = new StringBuffer(7);
    sBuffer3.append("string");
    sBuffer3.append(num1);
  • String format reference

back to top

Arithmetic Operators

  • addition: +
  • subtraction: -
  • multiplication: *
  • division: double double_name = 3.0/2; // output 1.5, 3/2 output 1
  • modulus: % divides the 2 numbers and returns the remainder
  • exponent: Math.pow(3, 2); // output 9
  • floor division: int integer_name = 3/2; // output 1

back to top

Comparison Operators

  • ==

    • reference comparison

      String s1 = new String("string value");
      String s2 = new String("string value");
      System.out.println(s1 == s2); // false

      String s3, s4;
      s3 = "string value";
      s4 = "string value";
      System.out.println(s3 == s4); // true
    • use equals method to compare string values

      String s1 = new String("string value");
      String s2 = new String("string value");
      System.out.println(s1.equals(s2)); // true
    • use equalsIgnoreCase to ignore cases

      String s1 = new String("String value");
      String s2 = new String("string value");
      System.out.println(s1.equals(s2)); // false
      System.out.println(s1.equalsIgnoreCase(s2)); // true
  • !=

  • >

  • <

  • >=

  • <=

  • instanceof

    • used for type checking
    • It can be used to test if an object is an instance of a class, a subclass, or an interface
    String s = "Hello";
    if (s instanceof java.lang.String) {
    System.out.println(true);
    }

back to top

Logical Operators

  • && and
  • || or
  • ^ exclusive or
  • ! not
  • ?= Ternary (shorthand if-then)

back to top

Bitwise Operators

// & is binary AND Operator, return 1 if both a and b are 1, count the 1s
a & b // 12 = ...0000 1100

// | is binary OR Operator, return 1 if either a and or b HAVE a 1
a | b // 61 = ...0011 1101

// ^ is binary XOR Operator, return 1 if both a and b are not 1 or 0
a ^ b // 49 = ...0011 0001

// ~ is binary Complement Operator, invert everything, 1 change to 0 and vice versa, count the 0s
~a // -61 = ...1100 0011

// << is binary left shift, shift everything to the left by n digit(s)
a << 2 // 240 = ...1111 0000

// <<< is Unsigned Left shift operator

// >> is Sign-propagating right shift, a binary right shift, shift everything to the right by n digit(s)
a >> 2 // 15 = ...0000 1111
c >> 2 // 3 = ...0000 0010, count the 1s
c = -9 // -9 = ...1111 0111
c >> 2 // -3 = ...1111 1101, count the 0s

// >>> is Unsigned Right shift operator, shift everything to the right by n digits(s), leftmost will add n 0s
c >>> 2 // 2 = ...0000 0010, count the 1s
c = -9 // -9 = ...1111 0111
c >>> 2 // 1073741821 = 0011...1111 1101, count the 0s

back to top

Increment

  • x = x + 1;
  • x += 1;
  • ++x; pre-increment, add 1 now
  • x++; post-increment, display without addition now then add 1 later when called again

back to top

Getting Input

  • must import scanner library

    import java.util.Scanner;
    // print question
    System.out.println("What's your name?");

    // get raw input
    Scanner scanner = new Scanner(System.in);
    // convert raw value to string type
    // can read the input only till the space
    // It can't read two words separated by a space
    // places the cursor in the same line after reading the input
    String input = scanner.next();
    // reads input including space between the words till the end of line \n
    // Once the input is read, positions the cursor in the next line
    String input1 = scanner.nextLine();
    // convert raw value to int type
    Int input2 = scanner.nextInt();
  • single input

    String name;
    try (Scanner in = new Scanner(System.in)) {
    System.out.println("Enter your name: ");
    name = in.nextLine();
    }
    System.out.println("name is " + name);
  • multiple inputs

    String firstname, surname;
    try (Scanner in = new Scanner(System.in)) {
    System.out.println("Enter your first name and then your surname: ");
    firstname = in.nextLine();
    surname = in.nextLine();
    }
    System.out.println("name is " + firstname + " " + surname);

back to top

Arrays and Lists

  • Arrays
    • In Java, all arrays are dynamically allocated
      • Obtaining an array is a two-step process
        • First, you must declare a variable of the desired array type
        • Second, you must allocate the memory to hold the array, using new, and assign it to the array variable
      • Thus, in Java, all arrays are dynamically allocated
    • Arrays are stored in contagious memory [consecutive memory locations]
    • Since arrays are objects in Java, we can find their length using the object property length
      • This is different from C/C++, where we find length using sizeof
    • A Java array variable can also be declared like other variables with [] after the data type
    • The variables in the array are ordered, and each has an index beginning from 0
    • Java array can also be used as a static field, a local variable, or a method parameter
    • The size of an array must be specified by int or short value and not long
    • The direct superclass of an array type is Object
    • Every array type implements the interfaces Cloneable and java.io.Serializable
    • This storage of arrays helps us in randomly accessing the elements of an array [Support Random Access]
    • The size of the array cannot be altered(once initialized)
      • However, an array reference can be made to point to another array
    • can only have 1 primitive or object data type: string, int, etc.
      • primitive data are stored in the contiguous memory locations
      • non primitive data are stored in a heap segment
    • printing this only shows the memory
    • The elements in the array allocated by new will automatically be initialized to 0 (for numeric types), false (for boolean), or null (for reference types)
// Empty string array of desired array size
String[] stringArray = new String[length_of_desired_array];
// New string array with elements inside
String [] stringArray = new String [] {string1, string2,...}; // Method 1: array literal
String[] stringArray = {string1, string2,...}; // Method 2

// Add string array element, limited to array size
// Modify string array element value
stringArray[index] = element;

// Access an element
stringArray[index];

// Find array size
stringArray.length;

// get class object information, it will return the run-time type signature "array with component type string" for this example
stringArray.getClass(); // class [S

// get superclass information
stringArray.getClass().getSuperclass(); // class java.lang.Object

// deep copy / clone for single-dimensional array
String stringArray2 = stringArray.clone();
System.out.println(stringArray == stringArray2); // true

// Copy array
int sourceArrStartingIndex = 1;
int destinationArrStartingIndex = 0;
int copiedArrLen = 2;
String[] copiedArr = new String[copiedArrLen];
System.arraycopy(sourceArr, sourceArrStartingIndex, copiedArr, destinationArrStartingIndex, copiedArrLen); // {"apple", "pear"}

// multidimensional array (subarrays are of the same size) / jagged arrays (subarrays can be of different sizes)
String[][] states = new String[3][2];
states[0][0] = "Japan";
states[0][1] = "Tokyo";

// clone for multi-dimensional array is a shallow copy
// because it creates a new array, but the subarrays are shared
String[][] states2 = states.clone();
System.out.println(states == states2); // false
  • Sorting an array

    • Sort array, can sort numbers, strings, etc.
    import java.util.Arrays;
    String[] sourceArr = {"orange", "apple", "pear"};
    Arrays.sort(sourceArr); // {"apple", "orange", "pear"}

List Interface

  • it is an interface, extends the Collection framework
  • This interface is dedicated to the data of the list type in which we can store all the ordered collection of the objects
  • This also allows duplicate data to be present in it
  • This list interface is implemented by various classes like ArrayList, Vector, Stack, etc.
    • Since all the subclasses implement the list, we can instantiate a list object with any of these classes
  • printing this shows the actual array
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Vector;
// method 1
List<String> list = Arrays.asList(element, element, ...)

// method 2
List<String> list = new ArrayList<>(); // from java 7 onwards redundant <String> is not required, can just use <>

// Add element to string List (left to right)
list.add(element);

// add an element at a specific index in the List
list.add(index, element);

// add another list into existing list from index
list.addAll(index, list2);

// updating element at index
list.set(index, element);

// Remove element from list at index
list.remove(index);

// Remove element from list with value
list.remove(element);

// Access an element
list.get(index);

// Find index of an element
list.indexOf(element);

// get length of list
list.size();

List <T> linkList = new LinkedList<> ();
List <T> vector = new Vector<> ();

Arraylist

  • it is a class, extends the AbstractList class and implements List interface

  • used to create a dynamic array that contains objects

  • creates an array of objects where the array can grow dynamically

    • size of the array automatically increases when we dynamically add and remove items
    • when the array becomes full and if we try to add an item
      • Creates a bigger-sized memory on heap memory
      • Copies the current memory elements to the new memory
      • New item is added now as there is bigger memory available now
      • Delete the old memory
  • it may be slower than standard arrays but can be helpful in programs where lots of manipulation in the array is needed

  • it is not Synchronized

    • Its equivalent synchronized class is Vector
  • can only have 1 data type

  • ArrayList can not be used for primitive types, like int, char, etc.

    • example: cannot be compiled

      ArrayList<int> list = new ArrayList<>();
import java.util.ArrayList;
import java.util.Array;
// arraylist with default values
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4));

// Empty string arrayList
ArrayList<String> arrayList = new ArrayList<String>();

// Add element to string arrayList (left to right)
arrayList.add(element);

// add an element at a specific index in the List
arrayList.add(index, element);

// add another list into existing list from index
arrayList.addAll(index, list2);

// Modify an element at index
arrayList.set(index, element);

// Access an element
arrayList.get(index);

// Remove element from arrayList at index
arrayList.remove(index);

// remove by value
arrayList.remove(Integer.valueOf(element)); // if element is a primitive
arrayList.remove(element); // if element is not a primitive

// Find arrayList size
arrayList.size();

// Remove all elements
arrayList.clear();

LinkedList

  • an implementation of the LinkedList data structure which is a linear data structure
    • where the elements are not stored in contiguous locations and every element is a separate object with a data part and address part
    • The elements are linked using pointers and addresses
    • Each element is known as a node
import java.util.LinkedList;

class Test {
public static void main(String[] args) {
LinkedList<Integer> ll = new LinkedList<Integer>();

// Appending new elements at the end of the list
for (int i = 1; i <= 5; i++)
ll.add(i);

System.out.println(ll);

// Remove element at index 3
ll.remove(3);

// Displaying the List after deletion
System.out.println(ll);

// Printing elements one by one
for (int i = 0; i < ll.size(); i++)
System.out.print(ll.get(i) + " ");
}
}

Vector

  • it provides us with dynamic arrays in Java
  • it may be slower than standard arrays
    • but can be helpful in programs where lots of manipulation in the array is needed
  • This is identical to ArrayList in terms of implementation
    • However, the primary difference between a vector and an ArrayList is that a Vector is synchronized and an ArrayList is non-synchronized
import java.util.Vector;

class Test {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();

// Appending new elements at the end of the list
for (int i = 1; i <= 5; i++) {
// add element
v.add(i);
v.add(0, 10); // insert element at index
if (i == 0)
v.set(0, i); // update element at index
}


System.out.println(v);

// Remove element at index
v.remove(index);

// remove by value of first occurrence
// method 1: if element is a primitive
v.remove(Integer.valueOf(element)); // method 1.1
v.remove(v.indexOf(element)); // method 1.2
v.remove((Integer) element); // method 1.3: change the int value to Integer value that matches the array element type
// method 2: if element is not a primitive
v.remove(element);

list.removeAll(Arrays.asList(element)); // remove all values with element

// Displaying the Vector after deletion
System.out.println(v);

// Printing elements one by one
for (int i = 0; i < v.size(); i++)
System.out.print(v.get(i) + " ");
}
}

Stack

  • models and implements the Stack data structure
  • The class is based on the basic principle of last-in-first-out
  • In addition to the basic push and pop operations, the class provides three more functions of empty, search and peek
  • The class can also be referred to as the subclass of Vector
import java.util.Stack;
import java.util.Iterator;

public class Test {
public static void main(String args[]) {
Stack<String> stack = new Stack<String>();
stack.push("Geeks");
stack.push("For");
stack.push("Geeks");
stack.push("Geeks");

// Iterator for the stack
Iterator<String> itr = stack.iterator();

// Printing the stack
while (itr.hasNext()) {
System.out.print(itr.next() + " ");
}

System.out.println();

stack.pop();

stack.remove(2);

// Iterator for the stack
itr = stack.iterator();

// Printing the stack
while (itr.hasNext()) {
System.out.print(itr.next() + " ");
}
}
}

Queue Interface

  • maintains the FIFO(First In First Out) order similar to a real-world queue line
  • This interface is dedicated to storing all the elements where the order of the elements matter
  • There are various classes like PriorityQueue, ArrayDeque, etc.
    • Since all these subclasses implement the queue, we can instantiate a queue object with any of these classes
import java.util.Queue;
import java.util.PriorityQueue;
import java.util.ArrayDeque;
Queue <T> pq = new PriorityQueue<> ();
Queue <T> ad = new ArrayDeque<> ();

Priority Queue

  • it is used when the objects are supposed to be processed based on the priority
  • It is known that a queue follows the First-In-First-Out algorithm
    • but sometimes the elements of the queue are needed to be processed according to the priority and this class is used in these cases
  • The PriorityQueue is based on the priority heap
  • The elements of the priority queue are ordered according to the natural ordering, or by a Comparator provided at queue construction time, depending on which constructor is used
import java.util.PriorityQueue;

class Test {
public static void main(String args[]) {
// Creating empty priority queue
PriorityQueue<Integer> pQueue = new PriorityQueue<Integer>();

// Adding items to the pQueue using add()
pQueue.add(10);
pQueue.add(20);
pQueue.add(15);

// Printing the top element of PriorityQueue
System.out.println(pQueue.peek());

// Printing the top element and removing it from the PriorityQueue container
System.out.println(pQueue.poll());

System.out.println(pQueue.peek());
}
}

Deque Interface

  • a slight variation of the queue data structure
  • also known as a double-ended queue, is a data structure where we can add and remove the elements from both ends of the queue
  • This interface extends the queue interface
    • The class which implements this interface is ArrayDeque
    • Since ArrayDeque class implements the Deque interface, we can instantiate a deque object with this class
import java.util.Deque;
import java.util.ArrayDeque;
Deque<T> ad = new ArrayDeque<> ();

ArrayDeque

  • implemented in the collection framework provides us with a way to apply resizable-array
  • This is a special kind of array that grows and allows users to add or remove an element from both sides of the queue
  • Array deques have no capacity restrictions and they grow as necessary to support usage
import java.util.ArrayDeque;

public class ArrayDequeDemo {
public static void main(String[] args) {
ArrayDeque<Integer> de_que = new ArrayDeque<Integer>(10);

de_que.add(10);
de_que.add(20);
de_que.add(30);
de_que.add(40);
de_que.add(50);

System.out.println(de_que);

de_que.clear();

// addFirst() method to insert the elements at the head
de_que.addFirst(564);
de_que.addFirst(291);

// addLast() method to insert the elements at the tail
de_que.addLast(24);
de_que.addLast(14);

System.out.println(de_que);
}
}

Set Interface

  • it is an unordered collection of objects in which duplicate values cannot be stored
  • This collection is used when we wish to avoid the duplication of the objects and wish to store only the unique objects
  • This set interface is implemented by various classes like HashSet, TreeSet, LinkedHashSet, etc.
    • Since all the subclasses implement the set, we can instantiate a set object with any of these classes
import java.util.Set;
import java.util.LinkedHashSet;
import java.util.TreeSet;
Set<T> hs = new HashSet<> ();
Set<T> lhs = new LinkedHashSet<> ();
Set<T> ts = new TreeSet<> ();

HashSet

  • it is an inherent implementation of the hash table data structure
  • The objects that we insert into the HashSet do not guarantee to be inserted in the same order
  • The objects are inserted based on their hashcode
  • This class also allows the insertion of NULL elements
import java.util.HashSet;

public class HashSetDemo {
public static void main(String args[]) {
HashSet<String> hs = new HashSet<String>();

hs.add("Geeks");
hs.add("For");
hs.add("Geeks");
hs.add("Is");
hs.add("Very helpful");

// Traversing elements
Iterator<String> itr = hs.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}

LinkedHashSet

  • it is very similar to a HashSet
  • The difference is that this uses a doubly linked list to store the data and retains the ordering of the elements
import java.util.LinkedHashSet;

public class LinkedHashSetDemo {
public static void main(String args[]) {
LinkedHashSet<String> lhs = new LinkedHashSet<String>();

lhs.add("Geeks");
lhs.add("For");
lhs.add("Geeks");
lhs.add("Is");
lhs.add("Very helpful");

// Traversing elements
Iterator<String> itr = lhs.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}

SortedSet Interface

  • it is very similar to the set interface
  • The only difference is that this interface has extra methods that maintain the ordering of the elements
  • The sorted set interface extends the set interface and is used to handle the data which needs to be sorted
  • The class which implements this interface is TreeSet
    • Since this class implements the SortedSet, we can instantiate a SortedSet object with this class
import java.util.SortedSet;
import java.util.TreeSet;
SortedSet<T> ts = new TreeSet<> ();

TreeSet

  • it uses a Tree for storage
  • The ordering of the elements is maintained by a set using their natural ordering whether or not an explicit comparator is provided
  • This must be consistent with equals if it is to correctly implement the Set interface
  • It can also be ordered by a Comparator provided at set creation time, depending on which constructor is used
import java.util.TreeSet;

public class TreeSetDemo {
public static void main(String args[]) {
TreeSet<String> ts = new TreeSet<String>();

ts.add("Geeks");
ts.add("For");
ts.add("Geeks");
ts.add("Is");
ts.add("Very helpful");

// Traversing elements
Iterator<String> itr = ts.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}

Map Interface

  • it is a data structure that supports the key-value pair mapping for the data
  • This interface doesn’t support duplicate keys because the same key cannot have multiple mappings
  • A map is useful if there is data and we wish to perform operations on the basis of the key
  • This map interface is implemented by various classes like HashMap, TreeMap, etc.
    • Since all the subclasses implement the map, we can instantiate a map object with any of these classes
import java.util.Map;
import java.util.HashMap;
import java.util.TreeMap;
Map<T> hm = new HashMap<> ();
Map<T> tm = new TreeMap<> ();

HashMap

  • it provides the basic implementation of the Map interface of Java
  • It stores the data in (Key, Value) pairs
  • To access a value in a HashMap, we must know its key
  • HashMap uses a technique called Hashing
  • Hashing is a technique of converting a large String to a small String that represents the same String so that the indexing and search operations are faster
  • HashSet also uses HashMap internally
import java.util.HashMap;

public class HashMapDemo {
public static void main(String args[]) {
HashMap<Integer, String> hm = new HashMap<Integer, String>();

hm.put(1, "Geeks");
hm.put(2, "For");
hm.put(3, "Geeks");

// Finding the value for a key
System.out.println("Value for 1 is " + hm.get(1));

// Traversing through the HashMap
for (Map.Entry<Integer, String> e : hm.entrySet())
System.out.println(e.getKey() + " " + e.getValue());
}
}

Collections static methods

addAll

  • it is used to add all the specified elements to the specified collection
  • Elements to be added may be specified individually or as an array
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Test {
public static void main(String[] args) {
List<String> items = new ArrayList<>();

items.add("Shoes");
items.add("Toys");

// Add one or more elements
Collections.addAll(items, "Fruits", "Bat", "Ball");

// Printing the list contents
for (int i = 0; i < items.size(); i++) {
System.out.print(items.get(i) + " "); // Shoes Toys Fruits Bat Ball
}
}
}

sort

  • it is used to sort the elements present in the specified list of Collection in ascending order
  • java.util.Collections.reverseOrder() is used to sort in the descending order
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Test {
public static void main(String[] args) {
List<String> items = new ArrayList<>();

items.add("Shoes");
items.add("Toys");

Collections.addAll(items, "Fruits", "Bat", "Mouse");

// Sorting according to default ordering using sort() method
Collections.sort(items);

// Printing the elements
for (int i = 0; i < items.size(); i++) {
System.out.print(items.get(i) + " "); // Bat Fruits Mouse Shoes Toys
}

System.out.println();

// Sorting according to reverse ordering
Collections.sort(items, Collections.reverseOrder());

// Printing the reverse order
for (int i = 0; i < items.size(); i++) {
System.out.print(items.get(i) + " "); // Toys Shoes Mouse Fruits Bat
}
}
}

binarySearch

  • returns the position of an object in a sorted list
  • To use this method, the list should be sorted in ascending order
    • otherwise, the result returned from the method will be wrong
  • If the element exists in the list, the method will return the position of the element in the sorted list
    • otherwise, the result returned by the method would be the (index where the element should have been present if exist - 1)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
public static void main(String[] args) {
List<String> items = new ArrayList<>();

items.add("Shoes");
items.add("Toys");
items.add("Horse");
items.add("Ball");
items.add("Grapes");

// Sort the List
Collections.sort(items);

// BinarySearch on the List
System.out.println(
"The index of Horse is "
+ Collections.binarySearch(items, "Horse")); // The index of Horse is 2

// BinarySearch on the List, value not found
System.out.println(
"The index of Dog is "
+ Collections.binarySearch(items, "Dog")); // The index of Dog is -2
}
}

copy

  • it is used to copy all the elements from one list into another
    • After the operation, the index of each copied element in the destination list will be identical to its index in the source list
    • The destination list must be at least as long as the source list
    • If it is longer, the remaining elements in the destination list are unaffected
    • values from source list will replace the values in the destination list, remaining elements in the destination list are unaffected
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Test {
public static void main(String[] args) {
List<String> destination_List = new ArrayList<>();

destination_List.add("Shoes");
destination_List.add("Toys");
destination_List.add("Horse");
destination_List.add("Tiger");

System.out.println(
"The Original Destination list is ");

for (int i = 0; i < destination_List.size(); i++) {
System.out.print(destination_List.get(i) + " "); // Shoes Toys Horse Tiger
}
System.out.println();

// Create source list
List<String> source_List = new ArrayList<>();

source_List.add("Bat");
source_List.add("Frog");
source_List.add("Lion");

// Copy the elements from source to destination
Collections.copy(destination_List, source_List);

// Printing the modified list
System.out.println(
"The Destination List After copying is ");

for (int i = 0; i < destination_List.size(); i++) {
System.out.print(destination_List.get(i) + " "); // Bat Frog Lion Tiger
}
}
}

disjoin

  • it is used to check whether two specified collections are disjoint or not
  • the 2 collections are disjoint if they have no elements in common
  • It returns true if the two collections do not have any element in common
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Test {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();

list1.add("Shoes");
list1.add("Toys");
list1.add("Horse");
list1.add("Tiger");

List<String> list2 = new ArrayList<>();

list2.add("Bat");
list2.add("Frog");
list2.add("Lion");

// Check if disjoint or not
System.out.println(
Collections.disjoint(list1, list2)); // true
}
}

back to top

Conditional Statement

// If else statement
if (condition_a) {
do_A;
} else if (condition_b) {
do_B;
} else {
do_something_else;
}


// {} not required if statement is a single line
if (condition_a)
do_A; // Single line statement
else if (condition_b)
do_B; // Single line statement
else
do_something_else; // Single line statement


// Ternary operator
condition_a ? do_A : do_B;


// Switch statement
switch(choice) { // choice value can only be primitive values in java 7, since java 8 strings are also accepted
case choice_A:
do_A;
break;
case choice_B:
do_B;
break;
default:
do_something_else;
break; // not required, but good to have in Java
}

back to top

Loops

// While loop
// declare_initial_conditional_value
int i = 0;
// Set condition
while (i<5) { // Start from 0 to 4
doThis;
// Include condition_increment_or_decrement;
i++;
// Can use break or continue to add additional functionality, or not use any
break; // Breaks out of the current closest enclosing loop
continue; // Goes to the top of the closest enclosing loop
}

// Do while loop: execute first before setting conditions, it is an example of exit control loop
// declare_initial_conditional_value
int i = 0;
do { // Start from 0 to 4
doThis;
// Include condition_increment_or_decrement;
i++;
// Set condition
} while (i<5);

// For loop
for (int i=0; i<5; i++) { // Start from 0 to 4
doThis;
// Can use break or continue to add additional functionality, or not use any
break; // Breaks out of the current closest enclosing loop
continue; // Goes to the top of the closest enclosing loop
}
// Reverse loop
for (int i=4; i>=0; i--) { // Start from 4 to 0
doThis;
}

// for each loop, can also loop collections with iterators
char[] chars = {'H', 'e', 'l', 'l', 'o'}; // an array can only have a single data type
for (char c : chars) { // for each element in the array
doThis;
}

// infinite for loop
for(;;){
//code to be executed
}

back to top

Instantiation

public class ClassName {
public String type; // instance variable

public static void main(String[] args) {
ClassName t = new ClassName(); // instantiation
t.type = "something";
t.display();

doSomething(); // can call static method directly
}

// instance method
private void display() {}

// static method
static void doSomething() {}
}

back to top

Functions

Functions

  • Memory Allocation for Methods Calls

    • Methods calls are implemented through a stack
    • Whenever a method is called a stack frame is created within the stack area and after that
      • the arguments passed to and the local variables and value to be returned by this called method are stored in this stack frame
      • when execution of the called method is finished, the allocated stack frame would be deleted
    • There is a stack pointer register that tracks the top of the stack which is adjusted accordingly
  • All the method names should start with a lowercase letter

  • If several words are used to form the name of the method, then each first letter of the inner word should be in Uppercase

  • Underscores are allowed, but not recommended

  • Also allowed are digits and currency symbols

  • example

    public void employeeRecords() // valid syntax
    public void EmployeeRecords() // valid syntax, but discouraged
// Normal functions
public static void myFunction() {
do_something;
}


// Normal function with parameters
public static void myFunction(dataType a){
do_something_with_a
}


// Normal function with return value (change void to data type to return)
public static int sum(int a){
return a + 1;
}
  • Lambda

    • interface

      • an interface that contains at most one abstract function
      • represents abstract concepts such as functions, actions, or predicates
      • Predicate: takes 1 argument, returns a Boolean
        import java.util.function.Predicate;
        Predicate<String> stringLen = (s) -> s.length() < 10;
        System.out.println(stringLen.test("Apples") + " - Apples is less than 10"); // true - Apples is less than 10
      • Consumer accepts single argument with no return value
        import java.util.function.Consumer;
        Consumer<String> consumerStr = (s) -> System.out.println(s.toLowerCase());
        consumerStr.accept("ABCDefghij"); // abcdefghij
      • Function accepts 1 argument and produces a result
        import java.util.function.Function;
        Function<Integer, String> converter = (num) -> Integer.toString(num);
        System.out.println("length of 26: " + converter.apply(26).length()); // length of 26: 2
      • Supplier represents a supplier of results
        import java.util.function.Supplier;
        Supplier<String> s = () -> "Java is fun";
        System.out.println(s.get()); // Java is fun
      • Runnable similar to Supplier
      // method 1
      Runnable r1 = new Runnable() {
      @Override
      public void run() {
      System.out.println("run");
      }
      };
      r1.run(); // run

      // method 2
      Runnable r2 = () -> System.out.println("run");
      r2.run(); // run
      • UnaryOperator single argument with a return value

        import java.util.function.UnaryOperator;
        UnaryOperator<String> str = (msg) -> msg.toUpperCase();
        System.out.println(str.apply("Msg in upper case")); // MSG IN UPPER CASE

        UnaryOperator<String> makeGreeting = "Hello, "::concat;
        System.out.println(makeGreeting.apply("World")); // Hello, World
      • BinaryOperator takes 2 arguments and returns value

        import java.util.function.BinaryOperator;
        BinaryOperator<Integer> add = (a, b) -> a + b;
        System.out.println(add.apply(10, 25)); // 35
      • BiFunction similar to BinaryOperator

        import java.util.function.BiFunction;
        BiFunction<String, String, String> concat = (a, b) -> a + b;
        String sentence = concat.apply("Today is ", "a great day");
        System.out.println(sentence); // Today is a great day
      • custom interface

        @FunctionalInterface  // not a must but better to have
        interface StringFunction {
        String doSomething(String str);
        }
        StringFunction strFunc = (s) -> s;
        System.out.println(strFunc.doSomething("test")); // test
      • method as lambdas

        import java.util.function.Function;
        import java.util.function.IntFunction;
        // method 1
        IntFunction<String> intToString = num -> Integer.toString(num);
        System.out.println(intToString.apply(123)); // 123

        // method 2: static method reference using ::
        IntFunction<String> intToString2 = Integer::toString;
        System.out.println(intToString2.apply(123)); // 123
        • lambdas made using a constructor

          import java.math.BigInteger;
          // method 1
          Function<String, BigInteger> newBigInt1 = (num) -> new BigInteger(num);
          System.out.println("expected value: 123456789, actual value: " + newBigInt1.apply("123456789")); // expected value: 123456789, actual value: 123456789

          // method 2
          Function<String, BigInteger> newBigInt2 = BigInteger::new;
          System.out.println("expected value: 123456789, actual value: " + newBigInt2.apply("123456789")); // expected value: 123456789, actual value: 123456789
        • lambdas made from an instance method

          import java.util.function.Consumer;
          // method 1
          Consumer<String> print1 = (str1) -> System.out.println(str1);
          print1.accept("Hello World"); // Hello World

          // method 2
          Consumer<String> print2 = System.out::println;
          print2.accept("Hello World"); // Hello World
// import java.util.ArrayList;
// import java.util.function.Consumer; // must import

// store non returning function
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(5);
Consumer<Integer> method = (n) -> { System.out.println(n); }; // can remove {} if is one liner

// method 1
numbers.forEach( method ); // 5

// method 2
numbers.forEach( (n) -> { System.out.println(n); } ); // 5
  • method overloading
static double addValues(String s1, String s2) {
double d1 = Double.parseDouble(s1);
double d2 = Double.parseDouble(s2);
double result = d1 + d2;
return result;
}

static double addValues(String s1, String s2, String s3) {
double d1 = Double.parseDouble(s1);
double d2 = Double.parseDouble(s2);
double d3 = Double.parseDouble(s3);
double result = d1 + d2 + d3;
return result;
}

back to top

Higher order functions

back to top

Hash Tables

  • Hash Tables, Dictionaries, Objects
// Map: it is an interface used to store data in key-value pair
import java.util.Map; // must import

// HashMap: it is the implementation class of the Map interface
import java.util.HashMap; // must import

// Set: it is an interface used to store data in value without duplicates
import java.util.Set;

// HashSet: It is the implementation class of the Set interface
import java.util.HashSet;
// declaration of maps
Map<String, String> map = new HashMap<>();
// Map<Integer, Boolean> map = new HashMap<>();

// add key value pair
map.put("jp", "Japan");
map.put("sg", "Singapore");
map.put("usa", "United States");
System.out.println(map); // { jp=Japan, sg=Singapore, usa=United States }

// get value with key
map.get("jp"); // "Japan"

// check if key exists
map.containsKey("kr"); // false

// remove key value pair with key
map.remove("sg"); // { jp=Japan, usa=United States }

// get a set of keys
// import java.util.Set; // must import
Set<String> keys = map.keySet(); // [ usa, jp ]


// declaration of sets
Set<Integer> numbers = new HashSet<Integer>();

// add value
numbers.add(1);

// check if value exists
numbers.contains(1); // true

// Check if a HashSet is empty
numbers.isEmpty();

// Find the size of a HashSet
numbers.size();

// Remove an element from a HashSet (The remove() method returns false if the element does not exist in the HashSet)
boolean isRemoved = numbers.remove(10);

// Remove all elements matching a given predicate
numbers.removeIf(num -> num % 2 == 0);

// Remove all elements from HashSet (clear it completely)
numbers.clear();

back to top

Collections

  • introduced in Java 7
  • it is a group of elements
  • can store, retrieve, manipulate, and communicate aggregate data
import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;
List<String> names = Arrays.asList("Paul", "Jane", "Michaela", "Sam");

// method 1
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b); // ascending order
}
});
System.out.println(names); // [Jane, Michaela, Paul, Sam]

// method 2 using lambda
Collections.sort(names, (a, b) -> b.compareTo(a)); // descending order
System.out.println(names); // [Sam, Paul, Michaela, Jane]
  • removing duplicates

    • eliminate duplicates and auto sort
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    List<Integer> duplicateNums = Arrays.asList(4, 3, 3, 3, 2, 1, 1, 1);
    System.out.println(duplicateNums.toString()); // [4, 3, 3, 3, 2, 1, 1, 1]

    // method 1
    Collection<Integer> noDuplicatesNums = new HashSet<>(duplicateNums);
    System.out.println(noDuplicatesNums.toString()); // [1, 2, 3, 4]

    // method 2
    Set<Integer> noDuplicatesNums2 = new HashSet<>(duplicateNums);
    System.out.println(noDuplicatesNums2.toString()); // [1, 2, 3, 4]
  • streams

    • the package contains interfaces for using streams
    • a stream represents a sequence of elements
    • the package was added to traverse collections
    • most stream operations take a lambda expression
    • Stream operations are either intermediate or terminal
      • Terminal operations are either void or return a type
        • e.g.: .collect(...)
      • Intermediate operations return the stream itself
        • e.g.: .sorted()
    • common operations include map, filter, forEach
    • elements in a stream cannot be changed
    import java.util.List;
    import java.util.Arrays;
    import java.util.stream.Collectors;

    public class Person {
    private String name;

    public Person(String name) {
    this.name = name;
    }

    public String getName() {
    return name;
    }
    }

    public class Main {
    public static void main(String[] args) {
    List<String> names = Arrays.asList("Paul", "Jane", "Michaela", "Sam");
    System.out.println(names.stream().collect(Collectors.joining(","))); // Paul,Jane,Michaela,Sam

    Person personA = new Person("Paul");
    Person personB = new Person("Jane");
    Person personC = new Person("Sam");
    List<Person> people = Arrays.asList(personA, personB, personC);

    // use .collect to aggregate names into a list
    // use .map to get the name
    List<String> names2 = people.stream().map(Person::getName).collect(Collectors.toList());
    System.out.println(names2); // [Paul, Jane, Sam]
    }
    }
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    Arrays.asList("red", "green", "blue").stream().sorted().findFirst().ifPresent(System.out::println);  // blue

    Stream.of("red", "green", "blue").filter(color -> color.startsWith("g")).forEach(System.out::println); // green

    List<String> collected = Stream.of("red", "green", "blue").map(string -> string.toUpperCase()).collect(Collectors.toList());
    System.out.println(collected.toString()); // [RED, GREEN, BLUE]
    import java.util.Arrays;
    import java.util.stream.IntStream;
    import java.util.stream.Stream;
    IntStream.range(1, 4).forEach(System.out::print);  // 123

    // find the average of the numbers squared
    Arrays.stream(new int[] {1, 2, 3, 4}).map(n -> n*n).average().ifPresent(System.out::println); // 7.5

    // map doubles to ints
    Stream.of(1.5, 2.3, 3.7).mapToInt(Double::intValue).forEach(System.out::print); // 123

back to top

Destructuring

back to top

Spread Operator

back to top

Rest parameters

static double myFunction(String ... args) {
String[] argsArr = args; // args is an array of arguments
}

back to top

Class

  • The first letter of the class should be in Uppercase (lowercase is allowed, but discouraged)

  • If several words are used to form the name of the class, each inner word’s first letter should be in Uppercase

    • Underscores are allowed, but not recommended

    • numbers and currency symbols are also allowed

      • latter are also discouraged because they are used for a special purpose
        • for inner and anonymous classes
    • example

      class MyJavaProgram    // valid syntax
      class 1Program // invalid syntax
      class My1Program // valid syntax
      class $Program // valid syntax, but discouraged
      class My$Program // valid syntax, but discouraged (inner class Program inside the class My)
      class myJavaProgram // valid syntax, but discouraged
  • if no constructor has been defined, a constructor with no args will be auto generated

  • if a constructor with args has been defined, a constructor with no args will not be auto generated

  • constructor can be overloaded with multiple constructors

public class Math {
public int arg1;
public int arg2;
public int total;
public static final String NAME = "Math"; // declaring a constant variable

// constructor (must have the same name as class name, no return data type)
public Math() {}

// overloading constructor
public Math(int arg0, int arg2) {
// this keyword is not a must, however, variable name must be different from the parameter
arg1 = arg0;
this.arg2 = arg2;
this.total = outerAdd(arg1, arg2);
}

public int innerAdd(int arg3) {
// this keyword is not a must, however, variable name must be different from the parameter
return this.arg1 + arg2 + arg3;
}

public static int outerAdd(int number1, int number2) {
return number1 + number2;
}

// An anonymous object: it is an object created without any name assigned to that object
int anonymousAdd(int number1, int number2) {
return number1 + number2;
}
}

class MainClass {
public static void main(String[] args) {
Math test = new Math(2, 4); // instantiation
// non-static variables or methods requires instantiation
System.out.println(test.total); // 6
System.out.println(test.innerAdd(2)); // 8
// static variables or methods does not requires instantiation
System.out.println(Math.outerAdd(4, 5)); // 9
// works similar to static methods
System.out.println(new Math().anonymousAdd(3, 2)); // 5
}
}

constructor chaining

  • the process of calling one constructor from another constructor with respect to current object
  • can be done in 2 ways
    • Within same class: It can be done using this() keyword for constructors in the same class
    • From base class: by using super() keyword to call the constructor from the base class
// within same class Using this() keyword
class Temp {
// default constructor 1
// default constructor will call another constructor
// using this keyword from same class
Temp() {
// calls constructor 2
this(5);
System.out.println("The Default constructor");
}

// parameterized constructor 2
Temp(int x) {
// calls constructor 3
this(5, 15);
System.out.println(x);
}

// parameterized constructor 3
Temp(int x, int y) {
System.out.println(x * y);
}

public static void main(String args[]) {
// invokes default constructor first
new Temp();
}
}
// Java program to illustrate Constructor Chaining to
// other class using super() keyword
class Base {
String name;

// constructor 1
Base() {
this("");
System.out.println("No-argument constructor of" +
" base class");
}

// constructor 2
Base(String name) {
this.name = name;
System.out.println("Calling parameterized constructor"
+ " of base");
}
}

class Derived extends Base {
// constructor 3
Derived() {
System.out.println("No-argument constructor " +
"of derived");
}

// parameterized constructor 4
Derived(String name) {
// invokes base class constructor 2
super(name);
System.out.println("Calling parameterized " +
"constructor of derived");
}

public static void main(String args[]) {
// calls parameterized constructor 4
Derived obj = new Derived("test");

// Calls No-argument constructor
// Derived obj = new Derived();
}
}

private access key

public class Person {
private int age = 0; // cannot be accessed other than within the class

// age can only be modified with the setter method
public void setAge(int age) {
this.age = age;
}

// age can only be retrieve with the getter method
public int getAge() {
return this.age;
}
}

protected access key

// class with protected method
package p1;

// Class A
public class A {
protected void display() {
System.out.println("test");
}
}
  • Calling protected function without extending the parent class

    package p2;

    // import all classes in package p1
    import p1.*;

    class B {
    public static void main(String args[]) {
    B obj = new B();
    // not be able to access the function “display” since child class has not inherited its value from the main class
    obj.display(); // throw an exception
    }
    }
    • throw an error Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: p2.B.display
  • Accessing a protected class

    package p1;

    // Class A
    protected class A {
    void display()
    {
    System.out.println("test");
    }
    }
    package p2;

    // import all classes in package p1
    import p1.*;

    // Class B is a subclass of A
    class B extends A {
    public static void main(String args[])
    {
    B obj = new B();
    obj.display(); // throw an exception
    }
    }
    • throw an error Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: p2.B.display
  • Accessing display function from the same package but different class

    public class C {
    public static void main(String args[]) {
    A obj = new A();
    obj.display(); // test
    }
    }
  • Accessing display function from a different package

    package p2;

    // import all classes in package p1
    import p1.*;

    // Class B is a subclass of A
    class B extends A {
    public static void main(String args[]) {
    B obj = new B();
    obj.display(); // test
    }
    }
  • Accessing a protected class by overriding to sub-class within same package

    public class C extends A {
    // overridden function
    protected void display() {
    System.out.println("overridden");
    }

    public static void main(String args[]) {
    C obj1 = new C();
    obj1.display(); // overridden
    }
    }

Anonymous classes

import java.util.Scanner;

public class Calculator {
public static void main(String[] args) {
ClassName c = new ClassName();
c.calculate();
}

// can be accessed from within the same class, subclasses of same packages,
// different classes of same packages, subclasses of different packages
protected void calculate() {
InputHelper helper = new InputHelper();
String s1 = helper.getInput("Please do something");
}

// only Calculator class can use this
class InputHelper {
// can only be accessed from the same class
private String getInput(String prompt) {
System.out.println(prompt);
Scanner sc = new Scanner(System.in);
return sc.nextLine();
}
}
}

inheritance

  • if a class isn't defined as final it can be extended
  • superclass members are inherited unless marked private
  • members of the grandparent class are not directly accessible
// enum
public enum Names {
JOHN, PETER;
}

// parent / base / superclass
public class Person {
private int age;
private Names name;
public boolean isAlive = true;
public final String TYPE = "Mammal";

public Person(int age, Names name) {
this.age = age;
this.name = name;
}

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

public int getAge() {
return this.age;
}

public Names getName() {
return this.name;
}

public void whoAmI() {
System.out.println("I am a Person");
}
}

// Inheritance: child / derived / subclass
public class John extends Person {
public John() {
super(25, Names.JOHN);
}

// Polymorphism: overriding the parent's method
@Override // use this even if it is not required for 2 benefits: take adv of compiler check, easier to read
public void whoAmI() {
System.out.println("I a John");
System.out.println(super.isAlive); // use super to get parent's attributes or methods
}
}

public class Main {
public static void main(String[] args) {
Person p = new Person(0, Names.JOHN);
p.whoAmI(); // "I am a Person
John j = new John();
j.setAge(25);
System.out.println(j.getAge());
System.out.println(j.getName());
j.whoAmI(); // "I am John"
}
}

Multiple inheritance

  • one class can have more than one superclass and inherit features from all parent classes
  • Java does not support multiple inheritances with classes
    • we can achieve multiple inheritances only through Interfaces
// Interface 1
interface PI1 {
// Default method
default void show() {
// Print statement if method is called from interface 1
System.out.println("Default PI1");
}
}

// Interface 2
interface PI2 {
// Default method
default void show() {
// Print statement if method is called from interface 2
System.out.println("Default PI2");
}
}

// Main class
// Implementation class code
class TestClass implements PI1, PI2 {
// Overriding default show method
public void show() {
// Using super keyword to call the show method of PI1 interface
PI1.super.show();

// Using super keyword to call the show method of PI2 interface
PI2.super.show();
}

// Main driver method
public static void main(String args[]) {
// Creating object of this class in main() method
TestClass d = new TestClass();
d.show();
}
}

interface

  • it is a contract that defines a set of methods with a particular signatures

  • any class that implement that interface must implement those methods

  • from Java 8 onwards

    • can now add default implementation for interface methods

      • This default implementation has a special use and does not affect the intention behind interfaces
    • can now define static methods in interfaces that can be called independently without an object

      • these methods are not inherited

        interface In1 {
        final int a = 10;
        static void display() {
        System.out.println("hello");
        }
        }

        // A class that implements the interface.
        class TestClass implements In1 {
        public static void main (String[] args) {
        In1.display();
        }
        }
// enum
public enum Names {
JOHN, PETER;
}

// interface: declaring of implementations are not required
// declaring of implementations in Android might be required during instantiation
public interface Human {
public void setAge(int age);

public int getAge();

public Names getName();

public void whoAmI();
}

// class that implements an interface
// if not all of the methods declared in the interface are implemented, an error will occur
// additional methods not declared in the interface can be declared
public class Person implements Human {
private int age;
private Names name;

public Person(int age, Names name) {
this.age = age;
this.name = name;
}

@Override // not required but better to be explicit
public void setAge(int age) {
this.age = age;
}

@Override
public int getAge() {
return this.age;
}

@Override
public Names getName() {
return this.name1;
}

@Override
public void whoAmI() {
System.out.println("I am a Person");
}
}

interface in a class

import java.util.*;

class Test {
// can have any access modifier
public interface Yes {
void show();
}
}

class Testing implements Test.Yes {
public void show() {
System.out.println("show method of interface");
}
}

class A {
public static void main(String[] args) {
Test.Yes obj;
Testing t = new Testing();
obj=t;
obj.show(); // show method of interface
}
}

interface in another interface

import java.util.*;

interface Test {
// must be default or public access modifier
interface Yes {
void show();
}
}

class Testing implements Test.Yes {
public void show() {
System.out.println("show method of interface");
}
}

class A {
public static void main(String[] args) {
Test.Yes obj;
Testing t = new Testing();
obj = t;
obj.show(); // show method of interface
}
}

Marker interface

  • It is an empty interface (no field or methods)

  • Examples of marker interface are Serializable, Cloneable and Remote interface

    • All these interfaces are empty interfaces
  • cloneable interface

    • it is present in java.lang package
    • There is a method clone() in Object class
      • A class that implements the Cloneable interface indicates that it is legal for clone() method to make a field-for-field copy of instances of that class
      • Invoking Object’s clone method on an instance of the class that does not implement the Cloneable interface results in an exception CloneNotSupportedException being thrown
      • By convention, classes that implement this interface should override Object.clone() method
    import java.lang.Cloneable;

    // By implementing Cloneable interface we make sure that instances of class A can be cloned
    class A implements Cloneable {
    int i;
    String s;

    public A(int i,String s) {
    this.i = i;
    this.s = s;
    }

    // Overriding clone() method by simply calling Object class clone() method
    @Override
    protected Object clone() throws CloneNotSupportedException {
    return super.clone();
    }
    }

    public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
    A a = new A(20, "GeeksForGeeks");

    // cloning 'a' and holding new cloned object reference in b
    // down-casting as clone() return type is Object
    A b = (A) a.clone();

    System.out.println(b.i); // 20
    System.out.println(b.s); // GeeksForGeeks
    }
    }
  • Serializable interface

    • Serializable interface is present in java.io package
    • It is used to make an object eligible for saving its state into a file
      • This is called Serialization
      • Classes that do not implement this interface will not have any of their state serialized or deserialized
      • All subtypes of a serializable class are themselves serializable
    import java.io.*;

    // By implementing Serializable interface we make sure that state of instances of class A can be saved in a file.
    class A implements Serializable {
    int i;
    String s;

    public A(int i,String s) {
    this.i = i;
    this.s = s;
    }
    }

    public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    A a = new A(20,"GeeksForGeeks");

    // Serializing 'a'
    FileOutputStream fos = new FileOutputStream("xyz.txt");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(a);

    // De-serializing 'a'
    FileInputStream fis = new FileInputStream("xyz.txt");
    ObjectInputStream ois = new ObjectInputStream(fis);
    A b = (A)ois.readObject();//down-casting object

    System.out.println(b.i+" "+b.s); // 20 GeeksForGeeks

    // closing streams
    oos.close();
    ois.close();
    }
    }
  • Remote interface

    • Remote interface is present in java.rmi package
    • A remote object is an object which is stored at one machine and accessed from another machine
      • to make an object a remote object, we need to flag it with Remote interface
      • Here, Remote interface serves to identify interfaces whose methods may be invoked from a non-local virtual machine
      • Any object that is a remote object must directly or indirectly implement this interface
      • RMI (Remote Method Invocation) provides some convenience classes that remote object implementations can extend which facilitate remote object creation

abstract

  • the abstract keyword is added
  • it can contain a mixture of fully implemented methods & abstract methods
    • abstract method is similar to a method in an interface
      • no implementation & only indicates method signature
      • any subclasses of an abstract method must implement that method
  • cannot be instantiated directly, only their subclasses can be instantiated
// enum
public enum Names {
JOHN, PETER;
}

// interface
public interface Human {
public void setAge(int age);

public int getAge();

public Names getName();

public void whoAmI();
}

// abstract parent / base / superclass
public abstract class Person implements Human {
private int age;
private Names name;

public Person(int age, Names name) {
this.age = age;
this.name = name;
}

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

@Override
public int getAge() {
return this.age;
}

@Override
public Names getName() {
return this.name1;
}

@Override
public void whoAmI() {
System.out.println("I am a Person");
}

// this means that every subclass of this class must declare its own origin
public abstract String getOrigin();
}

// child / derived / subclass
public class John extends Person {
public John() {
super(25, Names.JOHN);
}

@Override
public void whoAmI() {
System.out.println("I a John");
}

@Override
public String getOrigin() { // this must be declared here, else an error will occur
return "Japan";
}
}

public class Main {
public static void main(String[] args) {
// Person p = new Person(0, Names.JOHN); // abstract classes cannot be instantiated and will cause an error
John j = new John();
j.setAge(25);
System.out.println(j.getAge());
System.out.println(j.getName());
j.whoAmI(); // "I am John"
}
}

Abstract classes vs Interface

Abstract classesInterface
can have abstract and non-abstract methods. From Java 8, it can have default and static methods alsocan have only abstract methods
may contain non-final variablesVariables declared in a Java interface are by default final
can have final, non-final, static and non-static variableshas only static and final variables
can provide the implementation of the interfacecan’t provide the implementation of an abstract class
can be extended using the keyword “extends”can be implemented using the keyword “implements”
can extend another Java class and implement multiple Java interfacescan extend one or more Java interfaces
can have class members like private, protected, etc.are public by default

overloading

public class Sum {
public int sum() {
return 0;
}

public int sum(int x) {
return 0 + x;
}

// Overloaded sum().
// This sum takes two int parameters
public int sum(int x, int y) {
return (x + y);
}

// Overloaded sum().
// This sum takes three int parameters
public int sum(int x, int y, int z) {
return (x + y + z);
}

// Overloaded sum().
// This sum takes two double parameters
public double sum(double x, double y) {
return (x + y);
}

// Driver code
public static void main(String args[]) {
Sum s = new Sum();
System.out.println(s.sum());
System.out.println(s.sum(10));
System.out.println(s.sum(10, 20));
System.out.println(s.sum(10, 20, 30));
System.out.println(s.sum(10.5, 20.5));
}
}

back to top

Importing Libraries

  • Package in Java is a mechanism to encapsulate a group of classes, sub packages and interfaces
  • Packages are used for:
    • Preventing naming conflicts
      • For example there can be two classes with name Employee in two packages, college.staff.cse.Employee and college.staff.ee.Employee
    • Making searching/locating and usage of classes, interfaces, enumerations and annotations easier
    • Providing controlled access
      • protected and default have package level access control
      • A protected member is accessible by classes in the same package and its subclasses
      • A default member (without any access specifier) is accessible by classes in the same package only
    • Packages can be considered as data encapsulation (or data-hiding)
  • How packages work?
    • Package names and directory structure are closely related
      • For example if a package name is college.staff.cse, then there are three directories, college, staff and cse such that cse is present in staff and staff is present college
      • Also, the directory college is accessible through CLASSPATH variable, i.e., path of parent directory of college is present in CLASSPATH
        • The idea is to make sure that classes are easy to locate
    • Package naming conventions: Packages are named in reverse order of domain names
      • i.e., org.geeksforgeeks.practice
      • For example, in a college, the recommended convention is college.tech.cse, college.tech.ee, college.art.history, etc.
    • Adding a class to a Package: We can add more classes to a created package by using package name at the top of the program and saving it in the package directory
      • We need a new java file to define a public class, otherwise we can add the new class to an existing .java file and recompile it
// folder name that the current file is in, all other files that are in this folder can be imported without additional code
package com.example.demoapi.student;

// importing of user defined packages
import com.example.demoapi.student.utilities.Helper;

import java.time.LocalDate;
import java.time.Period;

// allows imports of all static members of the class (from java 5 and above)
import static java.time.LocalDate.*;

import javax.persistence.Entity; // imports Entity class from the persistence package
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

// method 2
import javax.persistence.*; // allows imports of all classes from the persistence package

@Entity
@Table
public class Student {
@Id
private Long id;
@Transient
private Integer age;

// using import java.time.LocalDate;
public Integer getAge1() {
return Period.between(dob, LocalDate.now()).getYears();
}

// using import static java.time.LocalDate.*;
public Integer getAge() {
return Period.between(dob, now()).getYears();
}
}
  • common built-in packages
    • java.lang: Contains language support classes(e.g classed which defines primitive data types, math operations), this package is automatically imported
    • java.io: Contains classed for supporting input / output operations
    • java.util: Contains utility classes which implement data structures like Linked List, Dictionary and support, for Date / Time operations
    • java.applet: Contains classes for creating Applets
    • java.awt: Contain classes for implementing the components for graphical user interfaces (like button, menus etc)
    • java.net: Contain classes for supporting networking operations

back to top

Type Conversions

  • implicit type conversion
    • occurs when an equation has multiple data types
    • small memory value to big memory value only
      • e.g.: byte to int
  • explicit type conversion
    • occurs when we use casting to change the data type
    • can convert big memory value to small memory value, however, data loss will occur
      • allow int to byte
System.out.println((3 + 5 + 8) / 3);  // 5
System.out.println((3 + 5 + 8) / 3.0); // 5.333333333333333

// implicit type conversion
byte b = 1;
int i = b;
float f = i;

// casting
// explicit type conversion
float pi = 3.14f;
int intPi = (int) pi; // 3

int num = 256;
byte b = (byte) num; // 0 (surplus value will assigned if converting big data type value to smaller data type value)

int num2 = 255;
byte b2 = (byte) num2; // 255

// convert number to strings (user helper class)
int i = 1234;
String str = Integer.toString(i); // "1234"

// convert string to double
String s = "423";
double d1 = Double.parseDouble(s);
System.out.println(d1); // 423.0
String doubleValue = "156.5";

// convert string to double
Double doubleObj = Double.parseDouble(doubleValue);
System.out.println(doubleObj); // 156.5

// convert double to byte
byte byteValue = doubleObj.byteValue();
System.out.println(byteValue); // -100

// convert double to int
int intValue = doubleObj.intValue();
System.out.println(intValue); // 156

// convert double to float
float floatValue = doubleObj.floatValue();
System.out.println(floatValue); // 156.5

// convert double to string
var stringValue = doubleObj.toString();
System.out.println(stringValue); // "156.5"

back to top

Find Data Type

back to top

JSON

back to top

Program Entry Point

  • the signature is public static void main(String… args)
  • public So that JVM can execute the method from anywhere
  • static The main method is to be called without an object
    • The modifiers public and static can be written in either order
  • void The main method doesn’t return anything
  • The method main() is the main entry point into a Java program
    • must be inside the class definition
    • The compiler executes the codes starting always from the main function
  • String[] The main method accepts a single argument, i.e., an array of elements of type String
class SomeClassName {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

back to top

Swapping values

int nums[] = {0, 1};
System.out.printf("%d, %d %n", nums[0], nums[1]); // 0, 1
int temp;
temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
System.out.printf("%d, %d %n", nums[0], nums[1]); // 1, 0

back to top

Error Handling

  • try: lets you test a block of code for errors

  • catch: lets you handle the error

    • use "Exception" keyword to catch all exception types
    • use specific exception types to catch that specific exception
      • exceptions are from java.lang library, so no imports are required
    • catch block can be chained (specific exception with highest priority should come first)
  • finally: lets you execute code, after try and catch, regardless of the result

    • very important for closing a file when an opened file in the try block triggered an exception
  • Built-in Exceptions

  • method 1

    class Test {
    public static void main(String[] args) {
    try {
    doSomething;
    } catch(SomeSpecificException e) {
    doSomethingIfErrorOccursRelatedToSomESpecificException;
    } catch(Exception e) { // e is an arg (mandatory), e can be used to print general or more detailed error
    e.printStackTrace();
    System.out.println(e.toString()); // prints exception information in the format of Name of the exception: description of the exception
    System.out.println(e.getMessage()); // prints only the description of the exception
    doSomethingIfErrorOccursRelatedToAllExceptions;
    } finally {
    doSomethingWhenTryAndCatchIsCompleted;
    }
    }
    }
  • method 2: Checked Exceptions

    • uses the throws keyword
    • exceptions that are checked at compile time
    class Test {
    public static void main(String[] args) throws IOException {
    doSomething; // do something, if error occurs, an exception will be raised
    }
    }
  • try with resources statement

    • only for java 8 or later versions, can't be used on android
    • it is a try statement that declares 1 or more resources
    • a resource is an object that must be closed after the program is finished with it
// type 1
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileWriter;

public class Main {
// try-with-resources
try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
return bReader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
}
}

// type 2
public class Main {
public static void main(String[] args) {
String sourceFile = "textfile"; // textfile path
String targetFile = "newtextfile"; // newtextfile path

// try-with-resources
try (
FileReader fReader = new FileReader(sourceFile); // read file
BufferedReader bReader = new BufferedReader(fReader); // read lines in file
FileWriter writer = new FileWriter(targetFile); // write file
) {
while (true) {
String line = bReader.readLine();
if (line == null) {
break;
} else {
writer.write(line + "\n");
}
}
System.out.println("File copied");
} catch (Exception e) {
e.printStackTrace();
}
}
}

back to top

Custom Error

  • must use either try catch statements or be inside a conditional statement to work
  • uses the throw keyword
// if using try catch, both throw and catch must handle the same Exception type
try {
// raise specific exception
throw new SpecificExceptionName("custom message");

// raise generic exception
throw new Exception("custom message");
} catch (SpecificExceptionName e) {
} catch (Exception e) {
}


if (true) {
// raise generic exception
throw new Exception("custom message");
}
  • custom exception
    • use cases
      • To catch and provide specific treatment to a subset of existing Java exceptions
      • Business logic exceptions: These are the exceptions related to business logic and workflow
        • It is useful for the application users or the developers to understand the exact problem
// This program throws an exception whenever balance amount is below Rs 1000
class MyException extends Exception {
//store account information
private static int accno[] = {1001, 1002, 1003, 1004};

private static String name[] = {"Nish", "Shubh", "Sush", "Abhi", "Akash"};

private static double bal[] = {10000.00, 12000.00, 5600.0, 999.00, 1100.55};

MyException() { }
MyException(String str) { super(str); }

public static void main(String[] args) {
try {
// display the heading for the table
System.out.println("ACCNO" + "\t" + "CUSTOMER" +
"\t" + "BALANCE");

// display the actual account information
for (int i = 0; i < 5 ; i++) {
System.out.println(accno[i] + "\t" + name[i] +
"\t" + bal[i]);

// display own exception if balance < 1000
if (bal[i] < 1000) {
MyException me =
new MyException("Balance is less than 1000");
throw me;
}
}
} catch (MyException e) {
e.printStackTrace();
}
}
}

back to top

Asynchronous

  • Handling asynchronous code (making it synchronous)

back to top

Math

import java.util.Random;

double number1 = 10.5;
double number2 = 15;

System.out.println("Math.abs(number1) " + (Math.abs(number1))); // Math.abs(number1) 10.5
System.out.println("Math.ceil(number1) " + (Math.ceil(number1))); // Math.ceil(number1) 11
System.out.println("Math.floor(number1) " + (Math.floor(number1))); // Math.floor(number1) 10
System.out.println("Math.max(number1, number2) " + (Math.max(number1, number2))); // Math.max(number1, number2) 15
System.out.println("Math.min(number1, number2) " + (Math.min(number1, number2))); // Math.min(number1, number2) 10.5
System.out.println("Math.pow(number1, 2) " + (Math.pow(number1, 2))); // Math.pow(number1, 2) 110.25
System.out.println("Math.round(number1) " + (Math.round(number1))); // Math.round(number1) 10
System.out.println("Math.sqrt(number1) " + (Math.sqrt(number1))); // Math.sqrt(number1) 3.24037034920393

System.out.println("Random Number Between 0 and 10 = " + (int)(Math.random() * 11 + 1 + 0)); // Math.random() * (max - min + 1) + min2 = change min2 to 1 to become between 1 and 10

Random rand = new Random();
System.out.println("Random Number Between 0 and 10 " + (rand.nextInt(11)));
System.out.println("Random Number Between 1 and 10 " + (rand.nextInt(10 - 1 + 1) + 1)); // rand.nextInt((max - min) + 1) + min;

back to top

Date and Time

  • must import
import java.util.Date;
import java.util.GregorianCalendar;
import java.text.DateFormat;
import java.util.Locale;
import java.time.LocalDateTime; // java 8
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Date d = new Date();  // Fri Jul 09 00:46:09 SGT 2021

// January = 0, Feburary = 1, ...
GregorianCalendar gc = new GregorianCalendar(2009, 1, 28);
gc.add(GregorianCalendar.DATE, 1); // add a day
Date d2 = gc.getTime(); // Sun Mar 01 00:00:00 SGT 2009

// format date
// method 1, with no specific style and locale
DateFormat df = DateFormat.getDateInstance();
System.out.println(df.format(d2)); // Mar 1, 2009
// method 2, with style and no locale
DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL);
System.out.println(df2.format(d2)); // Sunday, March 1, 2009
// method 3, with style and locale
Locale locale = new Locale("en_SG", "SGP"); // set as Singapore
DateFormat df3 = DateFormat.getDateInstance(DateFormat.FULL, locale);
System.out.println(df3.format(d2)); // 2009 Mar 1, Sun

LocalDateTime ldt = LocalDateTime.now(); // 2021-07-09T01:03:50.874932

// January = 1, Feburary = 2, ...
LocalDate ld = LocalDate.of(2009, 1, 28); // 2009-01-28

DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
System.out.println(dtf.format(ld)); // 2009-01-28

// format with a specific pattern
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("M/d/yyyy");
System.out.println(dtf2.format(ld)); // 1/28/2009

back to top

File System

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileWriter;

public class Main {
public static void main(String[] args) {
String sourceFile = "textfile"; // sourceFile path
String targetFile = "newtextfile"; // targetFile path

// try with resources statement, only available for java 8 and later versions
// can't be used on android
try (
FileReader fReader = new FileReader(sourceFile); // read file
BufferedReader bReader = new BufferedReader(fReader); // read lines in file
FileWriter writer = new FileWriter(targetFile); // write file
) {
while (true) {
String line = bReader.readLine();
if (line == null) {
break;
} else {
writer.write(line + "\n");
}
}
System.out.println("File copied");
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
String subDirectory = ""; // parent folder where the file is located
String sourceFilename = "textfile";
String targetFilename = "newtargetfile3";

// only for java 7 or later versions, not available for android
Path sourceFile = Paths.get(subDirectory, sourceFilename);
Path targetFile = Paths.get(subDirectory, targetFilename);

try {
// copy existing file contents into the new file
Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
}
  • using commons-io library to copy file
    • for latest versions and for android
    • download the commons-io jar file
    • create a lib folder inside the root folder of your project and move the commons-io jar file into it
    • then add the jar file into the class path
import org.apache.commons.io.FileUtils;  // common-io library

import java.io.File;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
File sourceFile = new File("path/to/file.txt");
File targetFile = new File("path/to/newfile.txt");

try {
// use commons-io
FileUtils.copyFile(sourceFile, targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
  • reading a text file over the internet
import java.net.URL;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

public class Main {
private static final String FLOWERS_FEED = "https://services.hanselandpetal.com/feeds/flowers.xml";

// adding the throws block allow code to run safely without having to write another try catch statement in the finally block
public static void main(String[] args) throws IOException {
InputStream stream = null;
BufferedInputStream buf = null;
try {
URL url = new URL(FLOWERS_FEED);
stream = url.openStream();
buf = new BufferedInputStream(stream);

StringBuilder sb = new StringBuilder();

while (true) {
int data = buf.read(); // gets a single character from stream, returns a character integer value if found else returns -1

if (data == -1) {
break;
} else {
sb.append((char) data); // translate the integer value into a character
}
}
System.out.println(sb);
} catch(IOException e) {
e.printStackTrace();
} finally {
// use finally to explicitly close the stream
stream.close();
buf.close();
}
}
}

back to top

Access modifier

  • These modifiers control the scope of class and methods
    • Access Modifiers:
      • private
        • most restricted, visible only to class they belong
      • default / package private
        • declared / defined without using any modifier
        • Accessible within the same class and package within which its class is defined
      • protected
        • visible to class they belong and any subclasses
      • public
        • visible to all classes
    • Non-access Modifiers:
      • final
        • constant value, value cannot be changed
        • methods cannot be overridden
      • abstract
      • strictfp
      • static
        • can be accessed without creating a class instance
modifiersame classsame packageoutside package by subclasseverywhere else
publicYYYY
protectedYYYN
no modifier aka "package private"YYNN
privateYNNN

back to top

Iterators

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator; // must import

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
  • using iterators to loop through collections
List<String> list = new ArrayList<>();
list.add("Japan");
list.add("China");
list.add("USA");

// method 1: using Iterator
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String value = iterator.next();
System.out.println(value);
}
// method 2: using forEach loop
for (String value: list) {
System.out.println(value);
}
// method 3: using List's forEach method, only available for Java 8 onwards, not included in android java 8
list.forEach(System.out::println); // method 1
list.forEach((s) -> {System.out.println(s}); // method 2


// loop hash maps with Iterator
Map<String, String> map = new HashMap<>();
map.put("jp", "Japan");
map.put("sg", "Singapore");
map.put("usa", "United States");
Set<String> keys = map.keySet();

Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
System.out.println(map.get(key));
}

// loop has maps with forEach
for (String key : keys) {
System.out.println(map.get(key));
}

back to top

Generators

back to top

Fetching Web Data

back to top

Enum

  • Enumerations are lists of possible values that you can use for any particular variable
  • An enumeration in java is called an enum class
// usual enums
public enum Names1 {
JOHN, PETER;
}

// setting a string value for enums
public enum Names2 {
JOHN("John"), PETER("Peter");

private String name;

Names2(String name) {
this.name = name;
}

@Override
public String toString() {
return this.name;
}
}

public class Person {
private Names1 name1 = Names1.JOHN; // using enum to set a constant variable
private Names2 name2 = Names2.JOHN;

public Names1 getName1() {
return this.name1;
}

public Names2 getName2() {
return this.name2;
}
}

public class Main {
public static void main(String[] args) {
Person p = new Person();
System.out.println(p.getName1()); // "JOHN"
System.out.println(p.getName2()); // "John"

Names1 arr[] = Names1.values();
System.out.println(arr[0].ordinal()); // 0
System.out.println(Names1.valueOf("JOHN")); // JOHN
}
}

back to top

Language Specific

Functional Interfaces

  • it is an interface that contains only one abstract method
    • They can have only one functionality to exhibit
    • From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface
    • A functional interface can have any number of default methods
      • examples: Runnable, ActionListener, Comparable
  • it is additionally recognized as Single Abstract Method Interfaces
    • they are also known as SAM interfaces
    • it is the new feature that provides users with the approach of fundamental programming
  • it is included in Java SE 8 with Lambda expressions and Method references in order to make code more readable, clean, and straightforward
    • they are interfaces that ensure that they include precisely only one abstract method
    • they are used and executed by representing the interface with an annotation called @FunctionalInterface
    • they can contain only one abstract method
      • However, they can include any quantity of default and static methods
  • there is no need to use the abstract keyword as it is optional to use the abstract keyword
    • because, by default, the method defined inside the interface is abstract only
    • We can also call Lambda expressions as the instance of functional interface
  • Before Java 8, we had to create anonymous inner class objects or implement these interfaces
class Test {
public static void main(String args[]) {
// create anonymous inner class object
new Thread(new Runnable() {
@Override public void run() {
System.out.println("New thread created");
}
}).start();
}
}
  • java 8

    class Test {
    public static void main(String args[]) {
    // lambda expression to create the object
    new Thread(() -> {
    System.out.println("New thread created");
    }).start();
    }
    }

@FunctionalInterface

  • it is used to ensure that the functional interface can’t have more than one abstract method

  • In case more than one abstract methods are present, the compiler flags an Unexpected @FunctionalInterface annotation message

  • it is not mandatory to use this annotation

  • built-in functional interfaces example

    • Runnable This interface only contains the run() method
    • Comparable This interface only contains the compareTo() method
    • ActionListener This interface only contains the actionPerformed() method
    • Callable This interface only contains the call() method
  • Java SE 8 included four main kinds of functional interfaces which can be applied in multiple situations

    • Consumer

      • the interface of the functional interface is the one that accepts only one argument or a gentrified argument
      • it has no return value, returns nothing
        • There are also functional variants of the Consumer
          • example: DoubleConsumer, IntConsumer, and LongConsumer
          • These variants accept primitive values as arguments
          • Other than these variants, there is also one more variant of the Consumer interface known as Bi-Consumer
    • Predicate

      • a function that accepts an argument and, in return, generates a boolean value as an answer
      • in java, it is a type of function which accepts a single value or argument and does some sort of processing on it, and returns a boolean (True/ False) answer
      • The implementation of the Predicate functional interface also encapsulates the logic of filtering in Java
        • a process that is used to filter stream components on the base of a provided predicate
      • Just like the Consumer functional interface, Predicate functional interface also has some extensions
        • example: IntPredicate, DoublePredicate, and LongPredicate
          • These types of predicate functional interfaces accept only primitive data types or values as arguments
      import java.util.*;
      import java.util.function.Predicate;

      class Test {
      public static void main(String args[]) {
      // create a list of strings
      List<String> names = Arrays.asList(
      "Geek", "GeeksQuiz", "g1", "QA", "Geek2");

      // declare the predicate type as string and use
      // lambda expression to create object
      Predicate<String> p = (s) -> s.startsWith("G");

      // Iterate through the list
      for (String st : names) {
      // call the test method
      if (p.test(st))
      System.out.println(st);
      // Geek
      // GeeksQuiz
      // Geek2
      }
      }
      }
    • Function

      • A function is a type of functional interface in Java that receives only a single argument and returns a value after the required processing
      • There are many versions of Function interfaces because a primitive type can’t imply a general type argument, so we need these versions of function interfaces
      • Many different versions of the function interfaces are instrumental and are commonly used in primitive types like double, int, long
      • The different sequences of these primitive types are also used in the argument
        • The Bi-Function is substantially related to a Function
          • it takes two arguments, whereas Function accepts one argument
      @FunctionalInterface
      public interface BiFunction<T, U, R> {
      R apply(T t, U u);
      ...
      }

      @FunctionalInterface
      public interface UnaryOperator<T> extends Function<T, U> {
      ...
      }
    • Supplier

      • The Supplier functional interface is also a type of functional interface that does not take any input or argument and yet returns a single output
      • This type of functional interface is generally used in the lazy generation of values
      • Supplier functional interfaces are also used for defining the logic for the generation of any sequence
        • example: The logic behind the Fibonacci Series can be generated with the help of the Stream.generate method, which is implemented by the Supplier functional Interface
      • The different extensions of the Supplier functional interface hold many other supplier functions
        • example: BooleanSupplier, DoubleSupplier, LongSupplier, and IntSupplier
        • The return type of all these further specializations is their corresponding primitives
@FunctionalInterface
interface Square {
int calculate(int x);
}

class Test {
public static void main(String args[]) {
int a = 5;

// lambda expression to define the calculate method
Square s = (int x) -> x * x;

// parameter passed and return type must be
// same as defined in the prototype
int ans = s.calculate(a);
System.out.println(ans);
}
}

Comparator Interface

  • it is used to order the objects of user-defined classes
  • A comparator object is capable of comparing two objects of the same class
  • Using a comparator, we can sort the elements based on data members
  • How do the sort() method of Collections class work?
    • Internally the Sort method call Compare method of the classes it is sorting
    • To compare two elements, it asks “Which is greater?”
      • Compare method returns -1, 0, or 1 to say if it is less than, equal, or greater to the other
    • It uses this result to then determine if they should be swapped for their sort
import java.io.*;
import java.lang.*;
import java.util.*;

class Student {
// Attributes of a student
int rollno;
String name, address;

public Student(int rollno, String name, String address) {
// This keyword refers to current instance itself
this.rollno = rollno;
this.name = name;
this.address = address;
}

// To print student details in main()
public String toString() {
// Returning attributes of Student
return this.rollno + " " + this.name + " "
+ this.address;
}
}

// Helper class implementing Comparator interface
class Sortbyroll implements Comparator<Student> {
// Sorting in ascending order of roll number
public int compare(Student a, Student b) {
return a.rollno - b.rollno;
}
}

// Helper class implementing Comparator interface
class Sortbyname implements Comparator<Student> {
// Sorting in ascending order of name
public int compare(Student a, Student b) {
return a.name.compareTo(b.name);
}
}

// Main class
class GFG {
public static void main(String[] args) {
// Creating an empty ArrayList of Student type
ArrayList<Student> ar = new ArrayList<Student>();

// Adding entries in above List
ar.add(new Student(111, "Mayank", "london"));
ar.add(new Student(131, "Anshul", "nyc"));
ar.add(new Student(121, "Solanki", "jaipur"));
ar.add(new Student(101, "Aggarwal", "Hongkong"));

System.out.println("Unsorted");

for (int i = 0; i < ar.size(); i++)
System.out.println(ar.get(i));

// Sorting student entries by roll number
Collections.sort(ar, new Sortbyroll());

System.out.println("\nSorted by rollno");

for (int i = 0; i < ar.size(); i++)
System.out.println(ar.get(i));

// Sorting student entries by name
Collections.sort(ar, new Sortbyname());

System.out.println("\nSorted by name");

for (int i = 0; i < ar.size(); i++)
System.out.println(ar.get(i));
}
}

Sort collection by more than one field

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

// Helper class representing a Student
class Student {
// Attributes of student
String Name;
int Age;

// Parameterized constructor
public Student(String Name, Integer Age)
{
// This keyword refers to current instance itself
this.Name = Name;
this.Age = Age;
}

public String getName() { return Name; }

public void setName(String Name) { this.Name = Name; }

public Integer getAge() { return Age; }

public void setAge(Integer Age) { this.Age = Age; }

// Method Overriding toString() method
@Override
public String toString()
{
return "Customer{"
+ "Name=" + Name + ", Age=" + Age + '}';
}

// Helper class implementing Comparator interface
static class CustomerSortingComparator
implements Comparator<Student> {

// Method 1
// To compare customers
@Override
public int compare(Student customer1,
Student customer2)
{

// Comparing customers
int NameCompare = customer1.getName().compareTo(
customer2.getName());

int AgeCompare = customer1.getAge().compareTo(
customer2.getAge());

// 2nd level comparison
return (NameCompare == 0) ? AgeCompare
: NameCompare;
}
}

// Method 2
public static void main(String[] args)
{

// Create an empty ArrayList to store Student
List<Student> al = new ArrayList<>();

// Create customer objects
Student obj1 = new Student("Ajay", 27);
Student obj2 = new Student("Sneha", 23);
Student obj3 = new Student("Simran", 37);
Student obj4 = new Student("Ajay", 22);
Student obj5 = new Student("Ajay", 29);
Student obj6 = new Student("Sneha", 22);

// Adding customer objects to ArrayList
al.add(obj1);
al.add(obj2);
al.add(obj3);
al.add(obj4);
al.add(obj5);
al.add(obj6);

// Iterating using Iterator before Sorting ArrayList
Iterator<Student> custIterator = al.iterator();

System.out.println("Before Sorting:\n");

// Holds true till there is single element remaining in List
while (custIterator.hasNext()) {

// Iterating using next() method
System.out.println(custIterator.next());
}

// Sorting using sort method of Collections class
Collections.sort(al,
new CustomerSortingComparator());

System.out.println("\n\nAfter Sorting:\n");

// after Sorting ArrayList
for (Student customer : al) {
System.out.println(customer);
}
}
}

Wrapper classes

Wrapper Classes

  • it is a class whose object wraps or contains primitive data types

  • When we create an object to a wrapper class, it contains a field and in this field, we can store primitive data types

    • In other words, we can wrap a primitive value into a wrapper class object
  • Need of Wrapper Classes

    • They convert primitive data types into objects. Objects are needed if we wish to modify the arguments passed into a method (because primitive types are passed by value)
    • The classes in java.util package handles only objects and hence wrapper classes help in this case
    • Data structures in the Collection framework, such as ArrayList and Vector, store only objects (reference types) and not primitive types
    • An object is needed to support synchronization in multithreading
  • autoboxing Automatic conversion of primitive types to the object of their corresponding wrapper classes

    import java.util.ArrayList;

    class Autoboxing {
    public static void main(String[] args) {
    char ch = 'a';

    // Autoboxing - primitive to Character object conversion
    Character a = ch;

    ArrayList<Integer> arrayList = new ArrayList<Integer>();

    // Autoboxing because ArrayList stores only objects
    arrayList.add(25);

    // printing the values from object
    System.out.println(arrayList.get(0)); // 25
    }
    }
  • unboxing Automatically converting an object of a wrapper class to its corresponding primitive type

    import java.util.ArrayList;

    class Unboxing {
    public static void main(String[] args) {
    Character ch = 'a';

    // unboxing - Character object to primitive conversion
    char a = ch;

    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    arrayList.add(24);

    // unboxing because get method returns an Integer object
    int num = arrayList.get(0);

    // printing the values from primitive data types
    System.out.println(num);
    }
    }
  • wrapping and unwrapping

    class WrappingUnwrapping {
    public static void main(String args[]) {
    // byte data type
    byte a = 1;

    // wrapping around Byte object
    Byte byteobj = new Byte(a);

    // int data type
    int b = 10;

    //wrapping around Integer object
    Integer intobj = new Integer(b);

    // float data type
    float c = 18.6f;

    // wrapping around Float object
    Float floatobj = new Float(c);

    // double data type
    double d = 250.5;

    // Wrapping around Double object
    Double doubleobj = new Double(d);

    // char data type
    char e='a';

    // wrapping around Character object
    Character charobj=e;

    // printing the values from objects
    System.out.println("Values of Wrapper objects (printing as objects)");
    System.out.println("Byte object byteobj: " + byteobj);
    System.out.println("Integer object intobj: " + intobj);
    System.out.println("Float object floatobj: " + floatobj);
    System.out.println("Double object doubleobj: " + doubleobj);
    System.out.println("Character object charobj: " + charobj);

    // objects to data types (retrieving data types from objects)
    // unwrapping objects to primitive data types
    byte bv = byteobj;
    int iv = intobj;
    float fv = floatobj;
    double dv = doubleobj;
    char cv = charobj;

    // printing the values from data types
    System.out.println("Unwrapped values (printing as data types)");
    System.out.println("byte value, bv: " + bv);
    System.out.println("int value, iv: " + iv);
    System.out.println("float value, fv: " + fv);
    System.out.println("double value, dv: " + dv);
    System.out.println("char value, cv: " + cv);
    }
    }

Number formatting

long longValue = 10_000_000;
// method 1
// using "import java.text.NumberFormat;"
NumberFormat formatter = NumberFormat.getNumberInstance();
String formatted = formatter.format(lognValue); // "10,000,000" (us locale)
// method 2
// using "import java.util.Locale;"
Locale locale = new Locale("da", "DK"); // set as Denmark
NumberFormat formatter = NumberFormat.getNumberInstance(locale);
String formatted = formatter.format(lognValue); // "10.000.000" (dk locale)

Currency formatting

long longValue = 10_000_000.00;
// method 1
// using "import java.text.NumberFormat;"
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String formatted = formatter.format(lognValue); // "$10,000,000.00" (us locale)
// method 2
// using "import java.util.Locale;"
Locale locale = new Locale("da", "DK"); // set as Denmark
NumberFormat formatter = NumberFormat.getCurrencyInstance(locale);
String formatted = formatter.format(lognValue); // "kr10.000.000,00" (dk locale)

Integer formatting

long longValue = 10_000_000.89;
// method 1
// using "import java.text.NumberFormat;"
NumberFormat formatter = NumberFormat.getIntegerInstance();
String formatted = formatter.format(lognValue); // "10,000,001" (us locale)
// method 2
// using "import java.util.Locale;"
Locale locale = new Locale("da", "DK"); // set as Denmark
NumberFormat formatter = NumberFormat.getIntegerInstance(locale);
String formatted = formatter.format(lognValue); // "10.000.001" (dk locale)

double colon operator / method reference operator

  • <Class name>::<method name>

  • can be used for

    • a static method
    import java.util.*;

    class GFG {
    // static function to be called
    static void someFunction(String s)
    {
    System.out.println(s);
    }

    public static void main(String[] args)
    {
    List<String> list = new ArrayList<String>();
    list.add("Geeks");
    list.add("For");
    list.add("GEEKS");

    // call the static method
    // using double colon operator
    list.forEach(GFG::someFunction);
    }
    }
    • an instance method
    import java.util.*;

    class GFG {
    // instance function to be called
    void someFunction(String s)
    {
    System.out.println(s);
    }

    public static void main(String[] args)
    {
    List<String> list = new ArrayList<String>();
    list.add("Geeks");
    list.add("For");
    list.add("GEEKS");

    // call the instance method
    // using double colon operator
    list.forEach((new GFG())::someFunction);
    }
    }
    • super method
    import java.util.*;
    import java.util.function.*;

    class Test {
    // super function to be called
    String print(String str)
    {
    return ("Hello " + str + "\n");
    }
    }

    class GFG extends Test {
    // instance method to override super method
    @Override
    String print(String s)
    {
    // call the super method
    // using double colon operator
    Function<String, String> func = super::print;

    String newValue = func.apply(s);
    newValue += "Bye " + s + "\n";
    System.out.println(newValue);
    return newValue;
    }

    // Driver code
    public static void main(String[] args)
    {
    List<String> list = new ArrayList<String>();
    list.add("Geeks");
    list.add("For");
    list.add("GEEKS");

    // call the instance method
    // using double colon operator
    list.forEach(new GFG()::print);
    }
    }
    • Instance method of an arbitrary object of a particular type
    import java.util.*;

    class Test {
    String str=null;

    Test(String s)
    {
    this.str=s;
    }
    // instance function to be called
    void someFunction()
    {
    System.out.println(this.str);
    }
    }

    class GFG {
    public static void main(String[] args)
    {
    List<Test> list = new ArrayList<Test>();
    list.add(new Test("Geeks"));
    list.add(new Test("For"));
    list.add(new Test("GEEKS"));

    // call the instance method
    // using double colon operator
    list.forEach(Test::someFunction);
    }
    }
    • a constructor
    import java.util.*;

    class GFG {
    // Class constructor
    public GFG(String s)
    {
    System.out.println("Hello " + s);
    }

    // Driver code
    public static void main(String[] args)
    {
    List<String> list = new ArrayList<String>();
    list.add("Geeks");
    list.add("For");
    list.add("GEEKS");

    // call the class constructor
    // using double colon operator
    list.forEach(GFG::new);
    }
    }

back to top