Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
9 views

JAVA Notes

1. Java allows developing and running programs across different systems through tools like the Java Development Kit (JDK) and Java Runtime Environment (JRE). 2. Key concepts in Java include keywords, comments, classes, packages, methods, and variables. 3. The main method is where program execution begins, and it must be declared in a class. Methods are declared within classes and contain code to define actions.

Uploaded by

Majd A-H
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

JAVA Notes

1. Java allows developing and running programs across different systems through tools like the Java Development Kit (JDK) and Java Runtime Environment (JRE). 2. Key concepts in Java include keywords, comments, classes, packages, methods, and variables. 3. The main method is where program execution begins, and it must be declared in a class. Methods are declared within classes and contain code to define actions.

Uploaded by

Majd A-H
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 236

The Beginning Of JAVA

General Information About Java


Java JDK: Allows to develop.
Java JRE (Libraries): Allows to run the programme in different systems.
Keyword: It’s a word with a predefined meaning in Java programming language syntax. Keywords may not be used as
identifiers for naming variables, classes, methods or other entities.
- The code written inside anything is called Implementation or body or block.
- If the code ends in the same line we write in the end: ;.
Redundant code: Useless code; such as, code that is never executed or code which is executed but has no external effect.
Comment/Note: Lines that the compiler won’t execute.
To write a note inside the code: 1- // one line note
2- /* */ If the note more than one line

Clean Code: Make classes and methods small and only have single responsibility.

javac anyNmae.java --> to compile


java anyNmae --> to run
Setting Java for Windows
Package: Contains classes.
- In the beginning of each class of the package : The name of the package is written.

Class: Contains members: method, Fields/Data members(Instance/Static variables), constructors, Blocks, Inner classes, etc.
- Classes exist in the package.

Access Modifier/ Behavior: The access limit.


- can be applied on classes, data members, methods and constructors, etc.
 Public: Any class can access it. Even outside the package.
 Default: Any class inside the same package can access it. The programme automatically consider it default if you don’t write the Access
modifier.
 Private: Only the same class can access it. Can’t be applied on classes.
 Protected: Any class inside the same package or outside the package through the inherited subclasses can access it. Can’t be applied on
the classes.

Name a class:
1. The first letter Should capital.
2. If the class name more than one word:

1. No space between the words


2. The
• Tofirst letter the
change of each
classword capital.
name: Highlight the name then right click on it then press refactor then rename.

Main Class (tester programe/tester class) : The class who contains the Main Method.
-The name of MainClass can be any name.
-it should be always static.

Note: A static class cannot be instantiated using the new keyword.


Method: Contains code to define actions.
- Methods exist in the classes.
• The programme runs the code exist inside the Main Method only.
Note:
- mutator = setter An array of String type and its name is args.

- accessor = getter
Method Header/ Method Signature:

1- Access Modifier/ Behavior: Explained.


2- Static: allows the method to use it in other classes without calling it by an object. Just by using the class name and
you can invoke it in the same class with only using the method name. and if there is a parameter you can put in the
brackets.
- When you don’t write static; then, it’s an instance method, and to invoke it you need an object. Explained later in the object.
3- Return Data point: The returns of a method when it invoked. Note: you can add return in void:
 Void: Returns nothing. (Returns nothing means no specific type). return();. But it will not have any effect.

 Primitive types: int, double, etc. It returns its type.


- Before the last bracket you write return and what you wanna return. Note: if you return a method then you
cannot put the display command in the
 Reference type: String, etc. It returns its type. method, you have to put it in the main
method.
- Before the last bracket you write return and what you wanna return. Note: return is for one value, if you
primitive and reference variables Explained later. need more then you should use array
(and it must be the same type).

5- Method Name: The first letter of the first word in any name in the java should be small letter, expect class name. The first letter of the
second and other words can be capital.
- The name of main method must be main.

6. Parameter/param(Formal Parameter): Variables in the method definition. Located inside the brackets. It can receives a value when the
method is called and the value won’t affect the actual parameter (call-by-value). And it is a local variable.
- The method can hold more than one parameter.
- you don't need a return type to put a parameter. You can have void with parameters.
-note: postcondition: is the output of the method.
-note: precondition: something is true before the method is called. NOTE: PART TWO OF METHODS EXPLAINED AFTER OVERRIDING.
Print Statement: Displays output.

.err.

- Inside the brackets we write what we want to print.


Argument: What is inside the print statement brackets.

(Delete whole line)


Variable: store a value. Defining data fields.
Make a variable:
1- Declaration: DataType VariableName; : int a;
2- Initialization: VariableName = value; : a = 0
3- Declaration and Initialization: DataType VariableName = value; : int a = 0;
- In coding the number 3,200,200,200 we write it 3_200_200_200 or 3200200200.
-The name of the variable also called Identifier. It may contains letters, digits (0 – 9), and underscore (_), it cannot: begin with a digit and contain spaces and
be reserved words. It should start with a lowercase letter.
- Identifiers can’t accept repeated names. Note: NN and nn are different names.
Data Type:
 Primitive Types:
 byte: Range: [-128, 127] = 1byte.
 short: Range: [-32K, 32K] = 2bytes.
 int: Range: [-2B, 2B] = 4bytes.
 long: 8bytes. Write “L”or”l” after the value.
 float: 4bytes. Write “F”or”f” after the value and before the ;.
 double: 8bytes. It’s optionally to Write “D”or”d” after the value.
 boolean: 1byte. Only two values: true or false.
 char: Range: could hold any character in the UNICODE. = 2bytes. The value should be inside one quote mark.
- You can write the code point or the hexadecimal value of it.

 Reference Types:
 Class
 Interface
 Array
 String

- variables of the same type can be declared together.


-
// First you must declare each one of them.
Constants / final: The value can’t change.
Casting: Storing a variable in bigger or smaller variable.
1- Widening Casting(Implicit): Storing a variable in a larger variable.

2- Narrowing Casting(Explicit): Storing a variable in a smaller variable.

Logical Operators:
 &&: and. Both terms should be true. and

 ||: or. One of the terms should be true. or

 !: not.
not

Comparison/ Relational Operators:


Important: relation operators two equal signs. But, in assignment just one equal sign.

-These Operators for primitive values. Also, objects support == and != operators.
Operators:
- Operate between variables and values.
Operator Meaning Example: Int x =22;
System.out.println(x+1); //Output: 23
+ Addition x=x+1;
System.out.println(x=x+1);
- Subtraction System.out.println(x-1); //Output: 21
* Multiplication System.out.println(x*8); //Output: 176
/ Division System.out.println(x/4); //Output: 5

% Modulus / Remainder Operator: The reminder after dividing System.out.println(x%4); //Output: 2


two numbers. (5*4=20, reminder is 2)

Increment System.out.println(++x); //Output: 23


Use the current value of number. Then increment by 1 for the next statement.
++ - If the ++ before the variable it called: postfix System.out.println(x++); //Output: 22
- If the ++ after the variable it called: unary System.out.println(x); //Output: 23

System.out.println(--x); //Output: 21
Use the current value of number. Then decrease it by 1 for the next statement.
-- Decrement System.out.println(x--); //Output: 22
System.out.println(x); //Output: 21

+= Addition assignment: System.out.println(x+=1); //Output: 23


Adds the right value to the left

-= Subtraction assignment System.out.println(x-=1); //Output: 21


*= Multiplication assignment System.out.println(x*=2); //Output: 44
/= Division assignment System.out.println(x/=4); //Output: 5
%= Modulus assignment System.out.println(x%=5); //Output: 2

= Assignment operator: to change the value of variable after the x=30;


variable has been declared.
Higher precedence.
Math Class: - These methods can be used in anyway not only “System.out.println”.
Method Name Meaning Example
Math.abs(value) Absolute value: Makes the number positive. System.out.println(Math.abs(-23)); //Output: 23
Math.ceil(value) Rounds up: Goes up to complete the number. System.out.println(Math.ceil(7.4)); //Output: 8.0
Math.floor(value) Rounds down: Goes down to complete the number. System.out.println(Math.floor(7.4)); //Output: 7.0
Math.max(value1,value2) Larger of two values System.out.println(Math.max(7,6)); //Output: 7
Math.min(value1,value2) Smaller of two values System.out.println(Math.min(7,6)); //Output: 6

Math.pow(base,exp) Base to the exponent power System.out.println(Math.abs(5,3)); //Output: 125

Math.sqrt(value) Square root System.out.println(Math.sqrt(9)); //Output: 3 (Square root of 9)

System.out.println(Math.log10(100)); //Output: 2
-- Formula:
Example:
Math.log10(value) Logarithm, base 10
--

Math.sin(value) - Math.cos(value) - Math.tan(value)


degree to radian:
Math.toDegrees(value) Convert degrees to radians
Note: = 3.14

radian to degree:
Math.toRadians(value) Convert radians to degrees
Note: = 3.14

System.out.println(Math.round(3.3f)); //Output: 3 (float to int)


Math.round(value) Nearest whole number
System.out.println(Math.round(3.3)); //Output: 3 (double to long)

System.out.println(Math.random());
Math.random() Random double between 0 and 1 System.out.println((int)(Math.random()*100)); //Output: the result will be
between 1 to 100
Method Name for a constant Meaning
Math.E 2.7182818…
Math.PI 3.1415926…
Class: is a template for the objects.
Object: is an instance (copy) of a class. With more details.
- When you make an object, it inherits all the variables and methods from the class.
- Sometimes we make a whole class just to make an object of it: Bean class.
- objects written in the main method.
- You can make an object of:
1. The main class.
2. Any class in the same package.
3. Any class outside your package by importing the class (Explained later).

Constructor: A method has the same name as the class.


- To make an object, there must be a Constructor. And if you don’t create one java will automatically creates a no-argument constructor:
default constructor.
How to make a constructor?
1- Access modifier
2- no return type not even void.
- The reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the object.
3- ClassName: The exact same name with the first later capital also.
4- parameters: if you want to give a variable every time a different value through an objects.
- The value passed to the variable through an object is called argument.
- Constructor without parameters is called no-argument constructor.
5- Body: It can have a body and will run when an object of it’s made.
explained later argument
Note: constructor helps us to assign the default value.

Note: to create a constructor fast: right click then generate then insert code then constructor. (alt + ins)

Encapsulation: means that the data and actions are combined into a single item which is a Class.
Reference Type:
- Class: is a Reference Type.
- a variable of an class: Its name a reference variable; Because, we use it to reference to an Copy of the class/object, (object reference
variable).
- Default value of any Reference variable is null.

Making a variable of an class:

- You can equal a class variable to another, same as any other variables types.

Reference an object:
Make a new object and assign it to the object reference variable using the new operator
-write an argument inside the brackets if there is a parameter in the constructor.
-The class variable can be declared first or in the same line with object creation.

Anonymous object: you can create an object without assigning it to a variable.

The usage of an object:

 Calling/Invoking an instance method: ObjectRefrenceVariable.methodName();


- The body of a method will run when its invoked.
- The methods of any class can be called in the mainMethod by making an object of the class then use the reference variable to call the
methods by its name.

 Anonymous object: New ClassName().methodName();

 Calling/Invoking an instance variable(Explained later).

- Static Method: You can invoke it without making an object. Just by using the class name with the method name:
ClassName.methodName(); or just by the method name : methodName();.
To use the class:
Restaurant p = new Restaurant();
p.setName("Alvin");
System.out.println("The name is " + p.getName());
System.out.println(p.toString());
// array of object
int size = 5;
Restaurant[] rest = new Restaurant[size];
// use foor loop
rest[0] = new Restaurant("OPQ","Serdang",30);
rest[1] = new Restaurant("LMN","Kajang",22);
System.out.println(rest[0].toString());
System.out.println(rest[1].toString());
*/
How to make an object of a class outside the package:

1. Import the class: Import strucher.package.Class; -You can import the whole package by using * like:
Import java.util*;

2. Make an object of the class you imported it


-Then you can access the methods of that class.

Note: your class shouldn’t be the same name as the imported class.
Note: to import all the classes and interfaces from a package write: import stucher.package.*;

Date Class (java.util.Date): Prints the right moment date in your computer.

SimpleDateFormat class(java.text.SimpleDateFormat): choose the format for thedaydate. calendar type


- In the object argument, write the complete date format and edit it as what you want :“E yyyy.MM.dd ‘at’ hh:mm:ss a zzz”
pm or am

- Method in SimpleDateFormat class: format(objectReferenceVariable of DateClass): to format DateClass.

Point Class (java.awt.Point): A point representing a location in (x,y) as integer (int).


- In the object argument: write the (x,y) point.
Timestamp with date:

Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


Date date = new Date();
String s = formatter.format(date);

Timestamp ts1 = Timestamp.valueOf(s);


System.out.println(ts1); //print as the normal format of date
System.out.println(ts1.getTime()); //Milliseconds
System.out.println(new Date(h)); //convert Millisecondsto date
Files Class (java.io.File): creates a file. Note: if the file is outside the package of the class
then you can put slash before the name of the
- io: input output. file, e.g.: (“/Data.txt”)
- In the object argument: The (“place path that the file will be in/the a file name.type”) for the file.

What if the file already exists or the computer don’t allow you to create the file on some places?
To check we use a method from the File class called: createNewFile().
- If there is no one already with the same name and the computer allow you to create.: It will create the file.
- If there is one already with the same name or the computer don’t allow you to create: It won’t create the file and your
project gonna collapse to prevent that from happing we use: try and catch: tries the code inside try, if there’s any error it
goes to catch and show the error(Exception) and run the code inside catch.

-Sometimes the computer won’t allow you to create files on C drive, but if you run NetBeans as administer then it might create it.

- There’s another method in the File Class called exists(): only to check if the file exists or not.
FileWriter Class (java.io.FileWriter): Access a file to write on it.
- In the object argument: The path of the file, but instead of write all of it, we use the getAbsolutePath() method form the File Class.

BufferedWriter Class (java.io.BufferedWriter): Write on the file.


-In the object argument: write the object reference variable of the FileWriter Class.

A method from BufferedWriter Class called write to write on the file.

FileInputStream class (java.io.FileInputStream): read from the file.


-In the object argument: write the object reference variable of the File Class.

• available() method: count the letters in the file.

• Read() method: print every letter on the file.

While Explained Later


Files: are used for permanent storage of large amounts of data.
Types of files:
Text file: sequence of characters (ASCII coding).
Binary file: sequence of bytes.

A stream: is a flow of data.


input stream: the data flows into the program.
output stream: the data flows out of the program.

- Writing to Text File:

Generics
- Writing to the end of a File: // because without this, every time you run PrintWriter class it will overwrite on the file.

- Reading from Text File:

//for the scanner.


Examples:
- Writing to Binary File:

- Reading from Binary File:

// you must know the sequence of the variables.

- To check for the end of a binary file:


try {
while(true) {
number = inputStream.readInt();
}
} catch (EOFException e) { } // EOFEException is used when we read the file until the end of it.

- File:
Types of variables:
Local Variable: Declared in the method and the usage of it inside that method. Without default values.
-The parameters considered a local veriables.
Data Members:
Static/Class Variable – Static Field: Declared as Static inside the class but outside the method. To
call it you don’t need an object Just the class name with the variable name: ClassName.variableName;.

Instance Variable/Field – Field - State: Declared inside the class but outside the method. Better to be declared as private. To call it you
need an object: objectReferenceVariable.VariableName;

Note: A static method can access the static variables but can’t access the instance variables.

This: is a keyword. we use it to address instance variable.


Block: is a sequence of zero or more statements enclosed in braces{}.

1. Block
- Method body, class body, etc.

2. Local Block: Written inside the method.

3. Instance Blocks: Need an object to execute.

4. Static Blocks: comes with static modifier, it doesn’t need an object.


Reference Type:
String: is a sequence of characters. String Class String Object
- predefined class in the Java library.
Reference
- a variable of a String : Is a reference variable, we use it to reference to a String object. Variable
- Default value is null
Ways to create a String:
1
2
3
- You can add two strings together using +.

Method from String Class:

contains Check if the string has a part of it.

Replace(“letter”,”letter”) Replace letter with letter.


(Or even part of the
sentence)
indexOf(String,indexWhereToStratFrom)

substring(Start, end) E.g.: letters.substring(5 , letters.length());

//Note: the end not include in the new string of the sub string.

Substring(index) --> means start the new string after the first index.

replaceAll method:
String s1="My name is Khan. My name is Bob. My name is Sonoo.";
String replaceString=s1.replaceAll("\\s","");

- "[A-z]" : means i want to delete all letters from A to z


- "[^A-z0-9]" : means i want to delete everything exept letters from A to z and numbers from 0 to 9
wrapper class
String to Number:
Each numeric wrapper class has two overloaded parsing methods to parse a numeric string into an appropriate numeric
value. based on 10 (decimal) or any specified radix if you want to write it (2 for binary, 8 for octal, and 16 for hexadecimal).

Integer.MAX_VALUE
Integer.MIN_VALUE

Character Wrapper Class:


.toUpperCase(charVariable);
.toLowerCase(charVariable);
.isUpperCase(charVariable);
.isLowerCase(charVariable);
.isWhitespace(charVariable);
.isLetter(charVariable);
.isDigit(charVariable);
.isLetterOrDigit(charVariable);
Scanner Class (java.util.Scanner): input.
- In the object argument: System.in.
Methods in Scanner Class:
- nextByte() :Input data of byte type.

- nextShort() :Input data of short type.

- nextInt() :Input data of int type.

- nextLong() :Input data of long type.

- nextFloat() :Input data of float type.

- nextDouble() :Input data of double type.

- nextBoolean() :Input data of boolean type.

- next() :Input data of String type. Reads a String that ends with a whitespace
character.

- nextLine() :Input data of String type. Reads an entire line of text.


NumberFormat Class (java.text.NumberFormat): format the numbers as currency or percentage.
Methods in NumberFormat Class:
- getCurrencyInstance() :Invoke the currency to use it for formatting.

- getPercentInstance(); :Invoke the percentage to use it for formatting.

- format(number) :Format the number.

Random Class (java.util.Random): generate random numbers of int, long, double, float, and boolean value.
- Object Reference Variable:
Methods in Random Class:
General information:

Sequence flow: Statements are executed one after the other in order.
Selection flow chooses among alternative courses of action. E.g.: If statements, switch statements.
- The statement is controlled by the boolean expression.
- Relational/Conditional operator can be used in the boolean expression.
- If there is more than one constraint/condition in the decision making, the logical operators are used to merge
multiple constraint/conditions.
Repetition flow specifies that an action is to be repeated while some condition remains true. E.g.: while statements.
If Statement: checks if an expression (condition) is true or false.
- If the condition is true: run the code inside the if.
- If the condition is false: run the code inside the else.
- If you want you can add more conditions, by else if. Then, if the
condition is false, it will first check the else if conditions if one of
them is right before goes to else.

String Comparison: DO NOT USE == operator. Use equals or equalsIgnoreCase methods.

Use compareTo and compareToIgnoreCase methods to know which came first according to ASCII ordering.

s1.compareTo(s2):
if s1 > s2, it returns positive number
if s1 < s2, it returns negative number
if s1 == s2, it returns 0

Note: you can use another way to compare between two strings,
which is: Integer.compare(s1.compareTo(s2), 0);
- The compare() method of Integer class of java.lang package
compares two integer values (x, y) given
as a parameter and returns the value zero if (x==y), if (x < y) then
it returns a value less than zero and
if (x > y) then it returns a value greater than zero.
Comparable and comparator both are an interface that can be used
to sort the elements of the collection. Comparator interface sort
collection using two objects provided to it,
whereas comparable interface compares" this" refers to the one
objects provided to it.
The Ternary Operator:

- doing it by using if statement:


while loop: executes code repeatedly based on boolean condition. while(condition){
//code
// increment or decrement
}

do while loop: executes code repeatedly based on boolean condition. Similar to while loop except that the condition is
checked after the statements inside do are executed. so do while loop guarantees the loop execution at least once.

Count-controlled loop: executed the statements for a fixed number of times.

Sentinel-controlled loop executed the statements repeatedly


until the sentinel is encountered.
break: Exit the loop.

continue: If the code of continue is true; then, don’t run the following code of the loop and go back run from the beginning
of the loop again.
Label: Exit the whole loops that inside the label. Break only exists the loop that include the break, so if there is nested loops,
it will not break all the loops.
Switch statement: checks which of the cases of a variable is true, If all of them are false then go to default.
How:
Make a variable and make cases of the variable.
- To exist the switch statement if one of the cases is true we write in the end of a case : break;
(All the cases and default written inside the switch statement).
 Switch statement only takes: byte, short, int, char.

You can write


it either way.
<This
Or this>

- No ignoring case in Switch for String.


- No boolean in switch

Common Error:
• switch (monthNum) {
case 1:
System.out.println("January");
case 2:
System.out.println("No break");
}
For loop: control flow statement that iterates a part of the program multiple times based on the condition and the times of
the repetition.
How:
1. Write the condition and the repetition inside the for loop bracket().
- Make a variable for the repetition times of the loop: Initialization condition.
- Write the condition.
- Write the variable increment or decrement: Update expression/condition.
2. Write the code you wanna loop inside the for loop curly brackets.

/ condition
Methods examples:
In the main method:
// methods with return value
String str = "Welcome UM";
System.out.print("The number of alphabet U and M in " +
str + " is ");
// System.out.println(getAlphabetUM(str));
int result = getAlphabetUM(str);
System.out.println(result); //The number of alphabet U and
M in Welcome UM is 2

In the main method:


//check precondition here before calling the method
//square(p,q)
int x=10, y=50, n=5;
randomnumber(n,x,y);
Methods examples:

In the main method: square();

In the main method: square(5,2);


In the main method:
int[] cntoddeven = getOddEven(number, 10, 50);
System.out.print("The random numbers are : ");
for(int value : number) {
System.out.print(value + " ");
}
System.out.println("\nThe number of odd number is " + cntoddeven[0]);
System.out.println("The number of even number is " + cntoddeven[1]);

In the main method:


int[] number = new int[10];
int cntodd = getOdd(number, 10, 50);
System.out.print("The random numbers are : ");
for(int value : number) {
System.out.print(value + " ");
}
System.out.println("\nThe number of odd number is " + cntodd);

In the main method:


// pass by value In the main method:
int num = 100; // reference type - array
special(num); int[] original = {1,2,3,4,5};
System.out.println(num); special(original);
//the value is 100
System.out.println(original[1]);
Reference Types:
Array: is a variable holds more than one value and can hold objects not only primitive types. Variable type values
- predefined class in the Java library.
Reference
- a variable of an array: Is a reference variable, we use it to reference to an array object. Variable

- Default value is null.


Ways to create an array:
1
2
Indexed
3 variable /
Means 10 values, so from 0 to 9; subscript.

4
5

Print an array:
For loop:

Element value number

Two dimensional for each loop :


For each loop:

this method can’t be used to modify the value of the element of the array.

Note: array: size is fixed.


array list: size is dynamic.

-If you change the array size then the old one would be
Notes: //You can add elements together
deleted.
-You can use final for an array then you cannot change the index.
Examples: Split method:
- The split method only use one char and it is for String only.

Split method for ArrayList:


ArrayList<String> illnesses = new ArrayList<>(Arrays.asList(illness_list.split(",")));

Multidimensional array:
can have more than one dimensional:
- 2 dim: tables, matrix. [raws][columns].
- 3 dim: 3D.

- to print the 2d: use two for loops. the first One for the
raws another for the columns.
Multidimensional array example:

A value is omnipresent if it exists in every subarray inside the


main array:

public class Program {


public static boolean omnipresent(int[][] arr, int val)
{
int c = 0;
for(int[] i: arr){
for(int j: i){
if(j == val){
c++;
break;
}
}
}
return c == arr.length;
}
}

toString:
Note:
when u create a new array and assign it to an old one, it will have the same memory location with the old one. so if you
change a value in the new array it will also change in the original.
For example:

Now the element [1] = 88 in the original and the newnum.

or you use .clone() method then you can make a copy of the original one and if you change the second array it won’t affect
the original one.
Inheritance: Class takes all the properties of another class and add it to his own class. Except private methods.

SuperClass/ParentClass/BaseClass/ancestor class: The class that gives his properties to another class.
SubClass/ChildClass/DerivedClass/ descendent class: The class that inherits and takes the properties.
-You can use the methods of the SuperClass in the Subclass by the object of the SubClass.
- A subclass automatically has all the instance variables (Fields), static variables and the public methods of superclass. But not private.
public class Animal{
}
public class Mammal extends Animal {
}
public class Dog extends Mammal {
} Inherit from Mammal and Animal.

extends: A keyword to inherit the properties of another class.

instanceof: checks if a class is inheriting from another class.

Notes:
- By default, the empty constructor of the subclass have the empty super constructor of the parent constructor. every constructor in
the child class will run the default constructor of the super class first.
- The child class cannot access private variables, so it must call the mutator or set the variables as protected when declaring them.

Question: How to call the constructor of the grandparent class? Call it in the constructor of parent the call the constructor of parent.

The Object class is the parent class of all the classes in java by default. And every class inherit from the Object class getClass method.
- Class c = getClass(); : getClass() method allows you to return information of a class:
- Example:
if (obj1.getClass() == obj2.getClass())
System.out.println("The objects are belongs to same class");
- c.getName(): will return: package.className
- c.getSimpleName(): will return: className
super keyword: after inherit a class you can call constructors or instance variables or methods from the parent class to
not repeat the code.
“Super” is like “this”
“this”: refers to an instance variable.
“super”: refers to a thing in the super class. And that thing is what you write after super.
The use of super keyword: 2) To access the method of parent class when child class has
1) To access the data members of parent class when both overridden that method.
parent and child class have member with same name. Note: if the method is
final it cannot be
override.
- an override method
cannot change the
return type of the
method definition. Also,
can change private to
public.
Note: When child class
doesn’t override the
parent class method
output: then we don’t need to
black use the super keyword
Output: eating... to call the parent class
white
barking... method.
3) To call the no-arg and parameterized constructor of Notes:
parent class - When u create an object of the child class: parent class
Note: With super(), the superclass no-argument constructor is constructor is executed first and then the child class constructor is
called. With super(parameter list), the superclass constructor executed. The compiler adds super()(which invokes the no-arg
with a matching parameter list is called. constructor of parent class) as the first statement in the
constructor of child class (with parameters or without).
- When u write super then the programme will not invoke it
automatically.
output: - super() must be added to the first statement of constructor.
animal is created - write in the child constructor the super keyword and write in the
dog is created super the variable that will equal the variable of the parent’s
constructor parameter and follow the order.
Overriding: using in the supclass from the superclass the same method with the same signature with adding or changing
whatever code inside the method or inherits the same code and add whatever.
- Overriding comes after inheriting the class. -If the method is Final, it cannot be override.

Note: Right Click on the supclass then generate what methods u want to override.

Overloading method: Using a method with the same name in the same class, but with changing the signature.
Examples:
// to make the type that in the parameter of Apple
constructor equal the type in fruit constructor.

Example part 1
Example part 2

// to make the type that in the parameter of Durian constructor equal the type in fruit constructor.
Abstract Class: Declared using abstract keyword.
It can have all the properties of a normal class and abstract methods(methods without body and cannot be static or private)
we can't create an object of an abstract class. The reference variable is used to refer to the objects of derived classes
(subclasses of abstract class).
- A subclass can be abstract even if its superclass is concrete.

Normal class(non-abstract class): It cannot have abstract methods. It can implement multiple interfaces, but it can extend
only one abstract class.
Interface: It’s a template for classes who inherit from it. The classes inherit the methods and by overriding change them as
what each class needs, by making an implementation for them.
- Only have abstract methods.
- Only have public access modifier.
- Doesn’t have constructors.
- Implements keyword to inherit from an interface, not extends.
- You can’t instantiate an object of an interface directly, Therefore, we use a class which implements the interface or use
a method that will give you as a return an instance of the interface.
- Interface can’t inherit a class. But it can inherit an interface with extends keyword or more than just one interface.
- Class can inherit more than just one interface.
- All variables must be public or static or final.
- by default you can call toString.
- Similar to an abstract class, but the intent of an interface is to specify common behavior for objects. For example,
you can specify that the objects are comparable, edible, cloneable using appropriate interfaces.

public int compareTo(Object other);


- The method return negative if calling object comes before the parameter object
- The method return positive if calling object comes after the parameter object
- The method return zero if calling object equals to the parameter object
Polymorphism (dynamic biding): Associate many meanings to one method.
- present all the childes classes with the parent class.
- The parent class need to be abstract class, so it represent the methods of the child class that is the same as the abstract
methods in the parent class. Or an interface.
- For the parent class to represent a child class method you need to create for the child class method, an abstract method for
it in the parent class. Also, the child class has to override every abstract method from the abstract class or the interface.
- object can’t be created using abstract class constructor.
-by default, you can call toString.

- Assigning an object of a derived class to a variable of base class is often called upcasting.
BaseClass a = new BaseClass;
DerivedClass b = new DerivedClass;

Examples:

//You can create also a Car a

}
Early Binding: The binding which can be resolved at compile time. When you have the same method in the parent and child
without override it and then call it by object then it will call only the parent class:
superclass A = new superclass();
superclass B = new subclass();
A.print(); //will print the parent class method
B.print(); //will print the parent class method

Late binding: In the late binding or dynamic binding, the compiler doesn’t decide the method to be called. So you override
the method in the child class and then when you make the objects and print it, it will print each one, not only the parent’s
method.
superclass A = new superclass();
superclass B = new subclass();
A.print(); //will print the parent class method
B.print(); //will print the child class method
ADT
You should write:
/**
* What the method is.
* Precondition: what it needs in order to run.
* Postcondition: what will happened after it runs.
* @param , state each parameter in one line.
* @return , state what it will return
*/
System.out.printf Method: display formatted output. NOTE: String.format is the same as printf
The syntax: System.out.printf(format specifiers, item1, item2, ..., items);
-Items must match the format specifiers in order and om exact type.

-writing the Format Specifier letter capital would give you the output in Uppercase.
Example:

Add more digits:

- You can use %.2f to specify a floating-point value with two digits after the decimal point.

You can change the number of spaces also.


If an item requires more spaces then the specified width, the width is automatically increased. Continue next Slide
Rather than spaces, you can add zeros in the digits:

- Output % in the format String: Write % twice.

- Display a number with comma separators by adding a comma in front of a number specifier.

- Decimal number to a hexadecimal number:


nested classes: is a class defined within the scope of another class or interface as a member.
 Non-static nested class/ inner class: have access to other members of the outer class, even if they are declared private.
1- Member inner class: Created within the class and outside the method. Class JavaOuterClass{
//code
Class JavaInnerClass{
//code
}
}

2- Anonymous inner class: has no name. use to override a method of class (abstract or concrete) or interface.
3- Local inner class: Created inside a method. Only available within the method.
 Static nested class: It cannot access non-static data members and methods. It can be accessed by outer class name. It can access
static data members of outer class including private.

Java Nested Interface: declared within another interface or class. The nested interface must be referred by the outer interface or
class, It can't be accessed directly.
- It must be public if it is declared inside the interface but it can have any access modifier if declared within the class.
- Nested interfaces are declared static implicitly. Class JavaOuterClass{ interface JavaOuterInterface{
//code //code
interface JavaInnerInterface{ interface JavaInnerInterface{
//code //code
} }
} }
Note: to know what is the exception, put in the catch
Exception Handling: Exception class, and then make the error and it will
- When an error occurs, we use exception handling, so the appear in the console what type of exception it is.
exception is caught and processed.
- try {
// try block if there is an error then it will jump to catch.
} catch (ExceptionOne e) {
// catch block
} catch (ExceptionTwo e) {
// catch block
} finally {
// Code to be executed whether or not an exception is
thrown, usually u need this to close file or database.
}

- predefined exceptions:
- IOException
- NoSuchMethodException
- FileNotFoundException
- NumberFormatException
- DivisionByZeroException
- ArrayIndexOutOfBoundsException

If you want to add exception handling to a method,


you can either add normal catch and try or you can
in the method header after closing the parameter - Throw new Exception: will let the catch and the getMessage
throw an exception, e.g.: throws IOException. to get the exception. (each condition throws one exception).
try {
// thread to sleep for 1000 milliseconds
Thread.sleep(1000);
} catch (Exception e)
{ System.out.println(e); }
Iterable

Go to element one then two etc.

Remove the element you at.


Lists: a popular abstract data type that stores data in sequential order.

Note: MyArrayList and MyLinkedList. These two classes have common operations, but different data fields.
Note: can choose either MyList as an interface or MyAbstractList as an abstract class to work with.
MyList
public interface MyList<E> extends java.lang.Iterable<E> {
/** Add a new element at the end of this list */
public void add(E e);

/** Add a new element at the specified index in this list */


public void add(int index, E e);

/** Clear the list */


public void clear();

/** Return true if this list contains the element */


public boolean contains(E e);

/** Return the element from this list at the specified index */
public E get(int index);

/** Return the index of the first matching element in this list.
* Return -1 if no match. */
public int indexOf(E e);

/** Return true if this list contains no elements */


public boolean isEmpty();

/** Return the index of the last matching element in this list
* Return -1 if no match. */
public int lastIndexOf(E e);
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e);

/** Remove the element at the specified position in this list


* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public E remove(int index);

/** Replace the element at the specified position in this list


* with the specified element and returns the new set. */
public Object set(int index, E e);

/** Return the number of elements in this list */


public int size();

/** Return an iterator for the list */


public java.util.Iterator<E> iterator();
}
public abstract class MyAbstractList<E> implements MyList<E> { MyAbstractList
protected int size = 0; // The size of the list

/** Create a default list */


protected MyAbstractList() {
}

/** Create a list from an array of objects */


protected MyAbstractList(E[] objects) {
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}

@Override /** Add a new element at the end of this list */


public void add(E e) {
add(size, e);
}

@Override /** Return true if this list contains no elements */


public boolean isEmpty() {
return size == 0;
}

@Override /** Return the number of elements in this list */


public int size() {
return size;
}

@Override /** Remove the first occurrence of the element e


* from this list. Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e) {
if (indexOf(e) >= 0) {
remove(indexOf(e));
return true;
}
else
return false;
}
}
The code in the next slide 
MyArrayList
public class MyArrayList<E> extends MyAbstractList<E> { /** Create a new larger array, double the current size + 1 */
public static final int INITIAL_CAPACITY = 16; private void ensureCapacity() {
if (size >= data.length) {
private E[] data = (E[])new Object[INITIAL_CAPACITY]; E[] newData = (E[])(new Object[size * 2 + 1]);
System.arraycopy(data, 0, newData, 0, size);
/** Create a default list */ data = newData;
}
public MyArrayList() { }
}
@Override /** Clear the list */
public void clear() {
/** Create a list from an array of objects */
data = (E[])new Object[INITIAL_CAPACITY];
public MyArrayList(E[] objects) { size = 0;
for (int i = 0; i < objects.length; i++) }
add(objects[i]); // Warning: don�t use super(objects)!
@Override /** Return true if this list contains the element */
} public boolean contains(E e) {
for (int i = 0; i < size; i++)
@Override /** Add a new element at the specified index */ if (e.equals(data[i])) return true;
public void add(int index, E e) {
return false;
ensureCapacity(); }

// Move the elements to the right after the specified index @Override /** Return the element at the specified index */
public E get(int index) {
for (int i = size - 1; i >= index; i--) checkIndex(index);
data[i + 1] = data[i]; return data[index];
}
// Insert new element to data[index]
private void checkIndex(int index) {
data[index] = e; if (index < 0 || index >= size)
throw new IndexOutOfBoundsException
// Increase size by 1 //("Index: " + index + ", Size: " + size);
("index " + index + " out of bounds");
size++; }
}
@Override /** Return the index of the first matching element @Override /** Replace the element at the specified position
* in this list. Return -1 if no match. */ * in this list with the specified element. */
public int indexOf(E e) {
public E set(int index, E e) {
for (int i = 0; i < size; i++)
if (e.equals(data[i])) return i; checkIndex(index);
E old = data[index];
return -1; data[index] = e;
} return old;
}
@Override /** Return the index of the last matching element
* in this list. Return -1 if no match. */
@Override
public int lastIndexOf(E e) {
for (int i = size - 1; i >= 0; i--) public String toString() {
if (e.equals(data[i])) return i; StringBuilder result = new StringBuilder("[");

return -1; for (int i = 0; i < size; i++) {


} result.append(data[i]);
if (i < size - 1) result.append(", ");
@Override /** Remove the element at the specified position
}
* in this list. Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public E remove(int index) { return result.toString() + "]";
checkIndex(index); }

E e = data[index]; /** Trims the capacity to current size */


public void trimToSize() {
// Shift data to the left
if (size != data.length) {
for (int j = index; j < size - 1; j++)
data[j] = data[j + 1]; E[] newData = (E[])(new Object[size]);
System.arraycopy(data, 0, newData, 0, size);
data[size - 1] = null; // This element is now null data = newData;
} // If size == capacity, no need to trim
// Decrement size }
size--;

return e;
}
@Override /** Override iterator() defined in Iterable */
public java.util.Iterator<E> iterator() {
return new ArrayListIterator();
}

private class ArrayListIterator


implements java.util.Iterator<E> {
private int current = 0; // Current index

@Override
public boolean hasNext() {
return (current < size);
}

@Override
public E next() {
return data[current++];
}

@Override
public void remove() {
MyArrayList.this.remove(current);
}
}
}
The code in the next slide 
MyLinkedList
public class MyLinkedList<E> extends MyAbstractList<E> { /** Add an element to the beginning of the list */
private Node<E> head, tail; public void addFirst(E e) {
Node<E> newNode = new Node<E>(e); // Create a new node
/** Create a default list */ newNode.next = head; // link the new node with the head
public MyLinkedList() { } head = newNode; // head points to the new node
size++; // Increase list size
/** Create a list from an array of objects */
public MyLinkedList(E[] objects) { if (tail == null) // the new node is the only node in list
super(objects); tail = head;
} }

/** Return the head element in the list */ /** Add an element to the end of the list */
public E getFirst() { public void addLast(E e) {
if (size == 0) { Node<E> newNode = new Node<E>(e); // Create a new for element e
return null;
} if (tail == null) {
else { head = tail = newNode; // The new node is the only node in list
return head.element; }
} else {
} tail.next = newNode; // Link the new with the last node
tail = tail.next; // tail now points to the last node
/** Return the last element in the list */ }
public E getLast() {
if (size == 0) { size++; // Increase size
return null; }
}
else {
return tail.element;
}
}
@Override /** Add a new element at the specified index /** Remove the last node and
* in this list. The index of the head element is 0 */ * return the object that is contained in the removed node. */
public void add(int index, E e) { public E removeLast() {
if (index == 0) {
if (size == 0) {
addFirst(e);
} return null;
else if (index >= size) { }
addLast(e); else if (size == 1) {
} Node<E> temp = head;
else { head = tail = null;
Node<E> current = head; size = 0;
for (int i = 1; i < index; i++) {
return temp.element;
current = current.next;
} }
Node<E> temp = current.next; else {
current.next = new Node<E>(e); Node<E> current = head;
(current.next).next = temp;
size++; for (int i = 0; i < size - 2; i++) {
} current = current.next;
}
}
/** Remove the head node and
* return the object that is contained in the removed node. */ Node<E> temp = tail;
public E removeFirst() { tail = current;
if (size == 0) { tail.next = null;
return null; size--;
} return temp.element;
else {
}
Node<E> temp = head;
head = head.next; }
size--;
if (head == null) {
tail = null;
}
return temp.element;
}
}
@Override /** Remove the element at the specified position in this @Override /** Override toString() to return elements in the list */
* list. Return the element that was removed from the list. */ public String toString() {
public E remove(int index) { StringBuilder result = new StringBuilder("[");
if (index < 0 || index >= size) {
return null; Node<E> current = head;
} for (int i = 0; i < size; i++) {
else if (index == 0) { result.append(current.element);
return removeFirst(); current = current.next;
} if (current != null) {
else if (index == size - 1) { result.append(", "); // Separate two elements with a comma
return removeLast(); }
} else {
else { result.append("]"); // Insert the closing ] in the string
Node<E> previous = head; }
}
for (int i = 1; i < index; i++) {
previous = previous.next; return result.toString();
} }

Node<E> current = previous.next; @Override /** Clear the list */


previous.next = current.next; public void clear() {
size--; size = 0;
return current.element; head = tail = null;
} }
}
@Override /** Return true if this list contains the element e */ @Override /** Replace the element at the specified position
public boolean contains(E e) { * in this list with the specified element. */
System.out.println("Implementation left as an exercise"); public E set(int index, E e) {
return true; System.out.println("Implementation left as an exercise");
} return null;
}
@Override /** Return the element at the specified index */
public E get(int index) { @Override /** Override iterator() defined in Iterable */
System.out.println("Implementation left as an exercise"); public java.util.Iterator<E> iterator() {
return null; return new LinkedListIterator();
} }

@Override /** Return the index of the head matching element in private void checkIndex(int index) {
* this list. Return -1 if no match. */ if (index < 0 || index >= size)
public int indexOf(E e) { throw new IndexOutOfBoundsException
System.out.println("Implementation left as an exercise"); ("Index: " + index + ", Size: " + size);
return 0; }
}

@Override /** Return the index of the last matching element in


* this list. Return -1 if no match. */
public int lastIndexOf(E e) {
System.out.println("Implementation left as an exercise");
return 0;
}
private class LinkedListIterator
implements java.util.Iterator<E> {
private Node<E> current = head; // Current index

@Override
public boolean hasNext() {
return (current != null);
}

@Override
public E next() {
E e = current.element;
current = current.next;
return e;
}

@Override
public void remove() {
System.out.println("Implementation left as an exercise");
}
}

private static class Node<E> {


E element;
Node<E> next;

public Node(E element) {


this.element = element;
}
}
}
ArrayList: flexible when you do not know the number of elements you want to use.
-ArrayList for objects only not primitive types.
Generic Classes: - Generics class may have more than 1 parameter. e.g. <E1, E2, E3>
Generic
Methods:
LinkedList:

Each node (an object) consists:


• A data item
• An address of another node (Pointers (pointer variables) are special
variables that are used to store addresses rather than values).
Creating each node manually:
Note:
- E only to receive any type.
- Node<E> to receive objects.
Note: the last node in the list, the value of its data field “next” is null. You can use this
property to detect the last node.
Note:
- If you want to reach index then use this: for(int x=0; x<index;x++)
- If you want to reach the node before index then use one of this: for(int x=1; x<index;x++) OR for(int x=0; x<index-1;x+
+)
public class MyLinkedList<E> {

private static class Node<E> {


E element;
Node<E> next;
public Node(E element) { this.element = element; }
}

private Node<E> head, tail;


private int size;

/** Create a default list */


public MyLinkedList() {
size=0;
head = tail =null;
}

/** Create a list from an array of objects */


public MyLinkedList(E[] objects) {
for(int x=0;x<objects.length;x++)
add(x,objects[x]);
}
}
public void addFirst(E e) {
if(tail==null){
head = tail = new Node<>(e);
}

Node<E> newNode = new Node<>(e);


newNode.next = head; //create pointer to current head
head = newNode; //new node created & assigned to new head
size++; //increase size
}
public void addLast(E e) {
if (tail == null) { //no node exist
head = tail = new Node<>(e);
}
else {
tail.next = new Node<>(e); //tail.next point to new Node
tail = tail.next; //new tail updated from tail.next
}
size++;
}
public void add(int index, E e) {
if (index == 0) addFirst(e); //since requested to add at index 0
else if (index >= size) addLast(e); //since requested to add at index=size
else {
Node<E> current = head; //set head to be a current node
for (int i = 1; i < index; i++) //traverse & stop before requested index
current = current.next;
Node<E> temp = current.next; //hold reference current.next
current.next = new Node<>(e); //current.next point to new node (refer α)
(current.next).next = temp; //get the reference from temp (refer β)
size++;
}
}
public E removeFirst() {
if (size == 0) return null; // no node then return null
else {
Node<E> temp = head; // copy head to temp node before delete
head = head.next; //set new head
size--; //reduce size
if (head == null) tail = null; //in case of head=null
return temp.element; //to know what we delete
}
}
Implementing removeLast()
public E removeLast() {
if (size == 0) return null;
else if (size == 1) //only 1 node
{
Node<E> temp = head;
head = tail = null;
//reset to know
size = 0;
return temp.element;
//to know what we delete
}
else
{
Node<E> current = head;
for (int i = 0; i < size - 2; i++)
current = current.next;
//stop 1 node before tail
Node<E> temp = tail;
//copy tail to temp b4 delete
tail = current;
//current become tail
tail.next = null;
//reset the next for tail
// to be null
size--;
return temp.element;
}
}
public E remove(int index) {
if (index < 0 || index >= size) return null; // to delete index of node not in range
else if (index == 0) return removeFirst(); //call removeFirst
else if (index == size - 1) return removeLast(); //call removeLast
else {
Node<E> previous = head; //Set head to be previous
for (int i = 1; i < index; i++) {
previous = previous.next; // stop before index that want to be deleted
}
Node<E> current = previous.next; //copy previous.next to current
previous.next = current.next; //set new point to from previous.next to current.next
size--; //reduce size
return current.element;
}
}
contains
public boolean contains(E e){
if(size==0) return false;
else{
Node<E> current = head;
for(int i=0; i<size; i++){
if(current.element .equals(e)){

System.out.println(current.element);
return true;
}
current = current.next;
}
}
return false;
}
Get

public E get(int index){


Node<E> temp = head;
for(int x=0; x<index;x++) temp=temp.next;
return temp.element;
}
lastIndexOf

public int lastIndexOf(E e){


if(size==0) return -1;
else {
int index=size-1;
for(int x=size-1;x>=0;x--){
if(get(x).equals(e)) return index;
index--;
}
return -1;
}
}
Print Reverse
public void reverse(){
for(int x=size-1;x>=0;x--){
System.out.println(get(x));
}
}

public E getMiddleValue(){
return get(size/2);
}
indexOf

public int indexOf(E e){


if(size==0) return -1;
else {
int index=0;
for(Node <E> current = head; current!=null;current= current.next){
if(current.element==e)return index;
index++;
}
return -1;
}
}
Set
public E set(int index, E e){
if (index<0 || index >= size-1) return null;
Node<E> temp = head;
for(int x=0; x<index;x++) temp=temp.next;
temp.element=e;
return temp.element;
}
public void clear(){
while (size!=0){
removeFirst();
size--;
}
}

public void replace(E e, E newE){


if(size==0)return;
for(int x=0;x<size;x++)
if(get(x).equals(e))
set(x,newE);
}
Doubly Linked List (two-way linked list):
-Each node contains two fields, called links(pointer), that are references to the previous and to the next node in the
sequence of nodes.
public class DoublyLinkedList<E> {

private Node<E> head;


private Node<E> tail;
private int size;

public DoublyLinkedList() {
size = 0;
this.head=null;
this.tail=null;
}
public void addFirst(E element) {
//create object tmp and set pointer of the new node
Node<E> tmp = new Node(element, head, null);
//set head.prev of current head to be linked to the new node
if(head != null ) {head.prev = tmp;}
head = tmp; //now tmp become head
//if no tail, then tmp set to be a tail
if(tail == null) { tail = tmp;}
size++;//increase number of node
System.out.println("adding: "+element);
}
public void addLast(E element) {
//create object tmp and set pointer of the previous node
Node<E> tmp = new Node(element, null, tail);
//set tail.next point to object tmp
if(tail != null) {tail.next = tmp;}
//now tmp become tail
tail = tmp;
//if no head, then tmp set to be a head
if(head == null) { head = tmp;}
size++;//increase number of node
System.out.println("adding: "+element);
}
Code next slide
public void add(int index, E element){
//index can only be 0 ~ size()
if(index < 0 || index > size)
throw new IndexOutOfBoundsException();
if(index == 0)
addFirst(element);
else if(index == size)
addLast(element);
else{
/* set from head and begin traverse
stop on required position */
Node<E> temp = head;
for(int i=0; i<index; i++){
temp = temp.next;
}
/* create object insert and set pointer of the next pointer
to the temp node and also set pointer of the prev pointer
to the temp.prev node
*/
Node<E> insert = new Node(element, temp, temp.prev);
//set pointer 'next' of the node temp.prev to new node insert
temp.prev.next = insert;
//set pointer 'prev' of the node temp to new node insert
temp.prev = insert;
size ++;
}
}
Traversing Forward
public void iterateForward(){
System.out.println("iterating forward..");
Node<E> tmp = head;
while(tmp != null){
System.out.print(tmp.element);
System.out.print(" ");
tmp = tmp.next;
}
}

public void iterateBackward(){


System.out.println("iterating backward..");
Node<E> tmp = tail;
while(tmp != null){
System.out.print(tmp.element+" ");
tmp = tmp.prev;
}
}
public E removeFirst() {
if (size == 0) throw new NoSuchElementException();
//copy head to node tmp
Node<E> tmp = head;
//head.next become a head
head = head.next;
//set pointer of prev of new head to be null
head.prev = null;
//reduce number of node
size--;
System.out.println("deleted: "+tmp.element);
return tmp.element;
}
public E removeLast() {
if (size == 0) throw new NoSuchElementException();
//copy tail to node tmp
Node<E> tmp = tail;
//tail.prev become a tail
tail = tail.prev;
//set pointer of next of new tail to be null
tail.next = null;
//reduce number of node
size--;
System.out.println("deleted: "+tmp.element);
return tmp.element;
}
Code next slide
public E remove(int index){
E element = null;
if(index < 0 || index >=size)
throw new IndexOutOfBoundsException();
if(index == 0)
element=removeFirst();
else if(index == size-1)
element=removeLast();
else{
Node<E> temp = head;
for(int i=0; i<index; i++){
temp = temp.next;
}
element = temp.element;
temp.next.prev = temp.prev;
temp.prev.next = temp.next;
temp.next = null;
temp.prev = null;
size --;
}
return element;
}
public void clear(){
Node<E> temp = head;
while(head != null){
temp = head.next;
head.prev = head.next = null;
head = temp;
}
temp = null;
tail.prev = tail.next = null;
size = 0;
}

Note: can also do this:


Head = tail = null;
Size =o
public int size() { return size; }

public boolean isEmpty() { return size == 0; }

public void display(){


if (head==null){
System.out.println("The list is empty");
return;
}
else {
Node<E> temp = head;
while(temp!=null) {
System.out.print(temp.element +" ");
temp = temp.next;
}
}
}
Stack
Implementing Stack
- using an array list to implement a stack is more efficient than a linked list since the
insertion and deletion operations on a stack are made only at the end of the stack.

- two ways to design the stack class using ArrayList:


- Using inheritance: You can define a stack (GenericStack) class by extending ArrayList class.
- Using composition: You can define an array list as a data field in the stack (GenericStack) class.
ublic class GenericStack<E> {
public GenericStack() {}
private java.util.ArrayList<E> list = new java.util.ArrayList<>();
public int getSize() {return list.size();}
public boolean isEmpty() {return list.isEmpty();}
public void push(E o) {list.add(o);}
public E peek(){
if(isEmpty()) throw new java.util.EmptyStackException();
return list.get(getSize() - 1);
}

public E pop() {
if(isEmpty()) throw new java.util.EmptyStackException();
E o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}

@Override
public String toString() { return "stack: " + list.toString();}
public static boolean isHTMLMatched(String html) {
Stack<String> buffer = new Stack<>( );
int j = html.indexOf('<'); // find first ’<’ character (if any)
while (j != -1) {
int k = html.indexOf('>', j+1); // find next ’>’ character
if (k == -1)
return false; // invalid tag
String tag = html.substring(j+1, k); // strip away < >
if (!tag.startsWith("/")) // this is an opening tag
buffer.push(tag);
else { // this is a closing tag
if (buffer.isEmpty( ))
return false; // no tag to match
if (!tag.substring(1).equals(buffer.pop( )))
return false; // mismatched tag
}
j = html.indexOf('<', k+1); // find next ’<’ character (if any)
}
return buffer.isEmpty( ); // were all opening tags matched?
}
Postfix Expressions
• Can be implemented using stacks
• Also called Reverse Polish Notation, is an alternative way of
representing mathematics expressions
• In a postfix evaluation format for an arithmetic expression, an
operator comes after its operands.
Errors
/** Evaluates a postfix expression.
@param postfix a string that is a valid postfix expression.
@return the value of the postfix expression. */
public static double evaluatePostfix(String postfix) {
GenericStack<Double> valueStack = new GenericStack<>();
String[] tokens = postfix.split(" ");
for (String token: tokens){
if(isNumeric(token))valueStack.push(Double.valueOf(token));
else if (token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/") || token.equals("^")){
Double operandTwo = valueStack.pop();
Double operandOne = valueStack.pop();
Double result = compute(operandOne, operandTwo, token);
valueStack.push(result);
}
} // end for
return (valueStack.peek());
} // end evaluatePostfix

public static boolean isNumeric(String str) {


try { double d = Double.parseDouble(str); }
catch(NumberFormatException nfe) { return false; }
return true;
}
private static Double compute(Double operandOne, Double operandTwo, String operator) {
double result;

switch (operator) {
case "+":
result = operandOne + operandTwo;
break;
case "-":
result = operandOne - operandTwo;
break;
case "*":
result = operandOne * operandTwo;
break;
case "/":
result = operandOne / operandTwo;
break;
case "^":
result = Math.pow(operandOne, operandTwo);
break;
default: // Unexpected character
result = 0;
break;
} // end switch
return result;
} // end compute
Queue
public class Queue<E> {
private java.util.LinkedList<E> list = new java.util.LinkedList<>();
public void enqueue(E e) { list.addLast(e); }
public E dequeue() { return list.removeFirst(); }
public int getSize() { return list.size(); }
@Override
public String toString() { return "Queue: " + list.toString(); }
}
Priority Queue
- In a priority queue, elements are assigned with priorities. When accessing
elements, the element with the highest priority is removed first.
- A priority queue has a largest-in, first-out behavior (however you need to
double check whether the larger the higher the priority, or the smaller the
higher the priority).
- For example, the emergency room in a hospital assigns priority numbers to
patients; the patient with the highest priority is treated first. The assumption
here the higher the number the higher the priority.
- A priority queue is a collection in which all elements have a comparison
(priority) ordering.
- It provides only simple access and update operations where a deletion always
removes the element of highest priority
public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue<String> queue1 = new PriorityQueue<>();
queue1.offer("Oklahoma");
queue1.offer("Indiana");
queue1.offer("Georgia");
queue1.offer("Texas");
System.out.println("Priority queue using Comparable:");
while (queue1.size() > 0) System.out.print(queue1.poll() + " ");

PriorityQueue<String> queue2 = new PriorityQueue<>(4, Collections.reverseOrder());


queue2.offer("Oklahoma");
queue2.offer("Indiana");
queue2.offer("Indiana");
queue2.offer("Georgia");
queue2.offer("Texas");
System.out.println("\n\nPriority queue using Comparator:");
while (queue2.size() > 0) System.out.print(queue2.poll() + " ");
}
}
public static class PriorityQueue2 {
public static void main(String... args ){
PriorityQueueComparator pqc=new PriorityQueueComparator();
PriorityQueue<String> pq=new PriorityQueue<String>(5,pqc);
pq.add("Jason");
pq.add("Ali");
pq.add("Muhamad");
for(String s:pq){
System.out.println(s);
}
}
}

public static class PriorityQueueComparator implements Comparator<String> {


public int compare(String s1, String s2) {
if (s1.length() < s2.length()) return -1;
if (s1.length() > s2.length()) return 1;
return 0;
}
}

Note: Implements the Comparator interface to use its compare method to arrange
the strings based on alphabetically ordaining.
public class Customer implements Comparable<Customer> {
private Integer id;
private String name;
public Customer(Integer id, String name) { this.id = id; this.name = name; }
public Integer getID() { return id; }
public String getName() { return name; }
@Override
public int compareTo(Customer c) { return this.getID().compareTo(c.getID()); }
@Override
public String toString() { return "Customer [ id=" + id + ", name=" + name + " ]" ; }
}

public class PriorityQueue2 {


public static void main(String[] args) {
PriorityQueue<Customer> customerQueue = new PriorityQueue<>(Collections.reverseOrder());
customerQueue.add(new Customer(3, "Donald" ));
customerQueue.add(new Customer(1, "Chong" ));
customerQueue.add(new Customer(2, "Ali" ));
customerQueue.add(new Customer(4, "Bala" ));

Customer customer = customerQueue.peek();


if (customer!=null) {
System.out.println(customer.getName() + " is in queue");
while ((customer = customerQueue.poll())!=null) System.out.println(customer);
}
}
}
public class WaitLine {
private Queue<Customer> line;
public class Customer { private int numberOfCustomers;
int arrivalTime; private int numberServed;
private int totalTimeWaited;
int transactionTime;
int customerNumber; public WaitLine() {
line= new Queue<>();
public Customer(int arrivalTime, int }
transactionTime, int customerNumber) {
public static void main(String[] args) {
this.arrivalTime = arrivalTime; WaitLine customerLine = new WaitLine();
this.transactionTime = transactionTime; customerLine.simulate(20, 0.5, 5);
customerLine.displayResults();
this.customerNumber = }
customerNumber;
/**
} * Simulates a waiting line with one serving agent.
public int getArrivalTime() { return * @param duration The number of simulated minutes.
* @param arrivalProbability A real number between 0 and 1, and the probability that
arrivalTime; } customer arrives at a given time.
public int getTransactionTime() { return * @param maxTransactionTime The longest transaction for a customer.
*/
transactionTime; } public void simulate(int duration, double arrivalProbability, int maxTransactionTime){
public int getCustomerNumber() { return int transactionTimeLeft=0;
for(int clock=0; clock<duration; clock++){
customerNumber; } if(Math.random()<arrivalProbability){
} numberOfCustomers++;
int transactionTime= (int)(Math.random()*maxTransactionTime+1);
Customer nextArrival = new Customer(clock,transactionTime,
numberOfCustomers);
line.enqueue(nextArrival);
System.out.println("Customer "+ numberOfCustomers + " enter line at time "+
clock+ ". Transaction Time is "+ transactionTime);
} //end if
} //end for
} //end method

public void displayResults(){


System.out.println("\nNumber served = "+ numberServed);
System.out.println("Total time waited = "+ totalTimeWaited);
double averageTimeWaited = ((double) totalTimeWaited) / numberServed;
System.out.println("Average time waited = "+averageTimeWaited);
int leftInLine = numberOfCustomers - numberServed;
System.out.println("Number left in line = "+ leftInLine);
} //end method

} //end class
Graph
Notes:

- A set of vertices, V and edges, G=(V,E).


- 2 vertices are “adjacent” to each other if they share the same edge.
- If, from vertex p, after travel along 1 or more edges, we eventually
reach vertex q, we say there is a “path” from p to q.
- Can be directed or undirected.
- Can be unweighted or weighted
- Each edge in a weighted graph carries a value – weight of the edge.
dimensional array

Adjacency matrix is fast and easy


to implement, but it
needs large space to hold the
matrix if n is large. So you should
consider the LinkedList.
class Vertex<T extends Comparable<T>, N extends Comparable <N>> { //to identify the vertices not the edges.
//Note: extends comparable, coz later u will invoke compareTo method for N and T
//N for the weight.
T vertexInfo; //vertex value
int indeg; //going in
int outdeg; //going out
Vertex<T,N> nextVertex; //next vertex in the graph linkedlist
Edge<T,N> firstEdge; //first edge

public Vertex() {
vertexInfo=null;
indeg=0;
outdeg=0;
nextVertex = null;
firstEdge = null;
}

public Vertex(T vInfo, Vertex<T,N> next) {


vertexInfo = vInfo;
indeg=0;
outdeg=0;
nextVertex = next;
firstEdge = null;
}
class Edge<T extends Comparable<T>, N extends Comparable <N>> {
Vertex<T,N> toVertex; //The vertex it has an adjacent with
N weight;
Edge<T,N> nextEdge; //reference to another edge with the main vertex
public Edge(){
toVertex = null;
weight = null;
nextEdge = null;
}
public Edge(Vertex<T,N> destination, N w, Edge<T,N> a) {
toVertex = destination;
weight = w;
nextEdge = a;
}
}
Graph Class

class Graph<T extends Comparable<T>, N extends Comparable <N>> {

Vertex<T,N> head;
//no need for a tail.
int size;

public Graph(){
head=null;
size=0;
}

public void clear() {head=null;}

public int getSize() {return this.size;} //get number of vertices

public int getIndeg(T v) {


if (hasVertex(v)) {
Vertex<T,N> temp = head;
while (temp!=null) {
if ( temp.vertexInfo.compareTo( v ) == 0 )
return temp.indeg;
temp=temp.nextVertex;
}
}
return -1; //if empty
}
public int getOutdeg(T v) {
if (hasVertex(v)) {
Vertex<T,N> temp = head;
while (temp!=null) {
if ( temp.vertexInfo.compareTo( v ) == 0 )
return temp.outdeg;
temp=temp.nextVertex;
}
}
return -1; //if empty
}

public boolean hasVertex(T v){


if (head==null)
return false;
Vertex<T,N> temp = head;
while (temp!=null) {
if (temp.vertexInfo.compareTo( v ) == 0) //if it is the vertex
return true;
temp=temp.nextVertex;
}
return false;
}
public boolean addVertex(T v){
if (!hasVertex(v)) { //if the vertex is not already in the graph then add it
Vertex<T,N> temp=head;
Vertex<T,N> newVertex = new Vertex<>(v, null);
if (head==null) head=newVertex; //if the graph is empty
else {
Vertex<T,N> previous=head;;
while (temp!=null) { //use previous to move to last vertex.
previous=temp;
temp=temp.nextVertex;
} //end while
previous.nextVertex=newVertex; //add vertex in the end of the list
} //end else
size++;
return true;
} //end if
else return false; //vertex is already in the graph
} //end method

public int getIndex(T v){


Vertex<T,N> temp = head;
int pos=0; //to hold the index number
while (temp!=null) { //loop to find the vertex
if ( temp.vertexInfo.compareTo( v ) == 0 ) //vertex is found
return pos;
temp=temp.nextVertex; //move temp to next vertex
pos+=1;
}
return -1;
}
public ArrayList<T> getAllVertexObjects() { //return all vertex info
ArrayList<T> list = new ArrayList<>();
Vertex<T,N> temp = head;
while (temp!=null) {
list.add(temp.vertexInfo);
temp=temp.nextVertex;
}
return list; //return arraylist
}

public ArrayList<Vertex<T,N>> getAllVertices() {


ArrayList<Vertex<T,N>> list = new ArrayList<>();
Vertex<T,N> temp = head;
while (temp!=null) {
list.add(temp);
temp=temp.nextVertex;
}
return list;
}

public T getVertex(int pos){


if (pos>size-1 || pos<0) //if the position is not valid
return null;
Vertex<T,N> temp = head;
for (int i=0; i<pos; i++)
temp=temp.nextVertex;
return temp.vertexInfo;
}
public boolean addUndirectedEdge (T vertex1, T vertex2, N w) {
if (head==null)
return false;
if (!hasVertex(vertex1) || !hasVertex(vertex2))
return false;
Vertex<T,N> vertex1_temp = head;
while (vertex1_temp!=null) {
if ( vertex1_temp.vertexInfo.compareTo( vertex1 ) == 0 ) {
Vertex<T,N> vertex2_temp = head;
while (vertex2_temp!=null) {
if ( vertex2_temp.vertexInfo.compareTo( vertex2 ) == 0 ) {

Edge<T,N> currentEdge_ForVertx1 = vertex1_temp.firstEdge;


Edge<T,N> newEdge_ForVertx1 = new Edge<>(vertex2_temp, w, currentEdge_ForVertx1);
vertex1_temp.firstEdge=newEdge_ForVertx1;

Edge<T,N> currentEdge_ForVertx2 = vertex2_temp.firstEdge;


Edge<T,N> newEdge_ForVertx2 = new Edge<>(vertex1_temp, w, currentEdge_ForVertx2);
vertex2_temp.firstEdge=newEdge_ForVertx2;

vertex1_temp.outdeg++;
vertex1_temp.indeg++;
vertex2_temp.outdeg++;
vertex2_temp.indeg++;
return true;
}
vertex2_temp=vertex2_temp.nextVertex;
}
}
vertex1_temp=vertex1_temp.nextVertex;
}
return false;
}
public boolean addEdge(T source, T destination, N w) {
if (head==null)
return false;
if (!hasVertex(source) || !hasVertex(destination))
return false;
Vertex<T,N> sourceVertex = head;
while (sourceVertex!=null) {
if ( sourceVertex.vertexInfo.compareTo( source ) == 0 ) { //means the same
// Reached source vertex, look for destination now
Vertex<T,N> destinationVertex = head;
while (destinationVertex!=null) {
if ( destinationVertex.vertexInfo.compareTo( destination ) == 0 ) {
// Reached destination vertex, add edge here
Edge<T,N> currentEdge = sourceVertex.firstEdge;
Edge<T,N> newEdge = new Edge<>(destinationVertex, w, currentEdge); //create the edge, the
reference of the another edge, will point to the old first edge.
sourceVertex.firstEdge=newEdge; //the new first edge will be the new one.
sourceVertex.outdeg++;
destinationVertex.indeg++;
return true;
}
destinationVertex=destinationVertex.nextVertex;
}
}
sourceVertex=sourceVertex.nextVertex;
}
return false;
}
public boolean hasEdge(T source, T destination){
if (head==null)
return false;
if (!hasVertex(source) || !hasVertex(destination))
return false; //if there the vertexes not exist in the destination or the source.
Vertex<T,N> sourceVertex = head;
while (sourceVertex!=null) {
if ( sourceVertex.vertexInfo.compareTo( source ) == 0 ) { //if found the source vertex
// Reached source vertex, look for destination now
Edge<T,N> currentEdge = sourceVertex.firstEdge;
while (currentEdge != null) { //look for destination vertex
if (currentEdge.toVertex.vertexInfo.compareTo(destination)==0)
// destination vertex found
return true;
currentEdge=currentEdge.nextEdge;
}
}
sourceVertex=sourceVertex.nextVertex;
}
return false;
}
public N getEdgeWeight(T source, T destination) {
N notFound=null;
if (head==null)
return notFound;
if (!hasVertex(source) || !hasVertex(destination))
return notFound;
Vertex<T,N> sourceVertex = head;
while (sourceVertex!=null) {
if ( sourceVertex.vertexInfo.compareTo( source ) == 0 ) {
// Reached source vertex, look for destination now
Edge<T,N> currentEdge = sourceVertex.firstEdge;
while (currentEdge != null) {
if (currentEdge.toVertex.vertexInfo.compareTo(destination)==0)
// destination vertex found
return currentEdge.weight;
currentEdge=currentEdge.nextEdge;
}
}
sourceVertex=sourceVertex.nextVertex;
}
return notFound;
}
public ArrayList<T> getNeighbours (T v) {
if (!hasVertex(v))
return null;
ArrayList<T> list = new ArrayList<T>();
Vertex<T,N> temp = head;
while (temp!=null) {
if ( temp.vertexInfo.compareTo( v ) == 0 ) {
// Reached vertex, look for destination now
Edge<T,N> currentEdge = temp.firstEdge;
while (currentEdge != null) {
list.add(currentEdge.toVertex.vertexInfo);
currentEdge=currentEdge.nextEdge;
}
}
temp=temp.nextVertex;
}
return list;
}

public void printEdges() {


Vertex<T,N> temp=head;
while (temp!=null) {
System.out.print("# " + temp.vertexInfo + " : " ); //print the vertex
Edge<T,N> currentEdge = temp.firstEdge;
while (currentEdge != null) { //print its edges
System.out.print("[" + temp.vertexInfo + "," + currentEdge.toVertex.vertexInfo +"] " );
currentEdge=currentEdge.nextEdge;
}
System.out.println();
temp=temp.nextVertex;
}
}
public boolean removeEdge(T source, T destination){
if(head==null){
return false;
}
if(!hasEdge(source,destination)){
return false;
}
Vertex<T,N> temp = head;
while(temp!=null){
if(temp.vertexInfo.compareTo(source) == 0){
Edge< T, N> currentEdge = temp.firstEdge;
if (currentEdge.toVertex.vertexInfo.compareTo(destination) == 0) {
// The first edge is the one we want to delete
temp.firstEdge = currentEdge.nextEdge;
currentEdge.nextEdge = null;
} else{
Edge<T,N> edge_to_delete = temp.firstEdge.nextEdge;
Edge<T,N> previous_edge = temp.firstEdge;
while(edge_to_delete!= null){
if(edge_to_delete.toVertex.vertexInfo.compareTo(destination)==0){
previous_edge.nextEdge = edge_to_delete.nextEdge;
edge_to_delete = null;
break;
}
previous_edge = edge_to_delete.nextEdge;
edge_to_delete = edge_to_delete.nextEdge;
}
}
temp.outdeg--;
currentEdge.toVertex.indeg--;
return true;
}
temp = temp.nextVertex;
}
return false;
}
}
public boolean removeVertex(T v){
if(head==null) return false;
else if(!hasVertex(v)) return false;
else{
//delete all the edges with another nodes
Vertex<T,N> temp = head;
while (temp!=null) {
if (hasEdge(temp.vertexInfo, v)) { //check if the temp has edges with vertex u want to delete
removeEdge(temp.vertexInfo, v);
}
temp= temp.nextVertex;
}

//now to delete the vertices


Vertex<T,N> current = head;
Vertex<T,N> prev = null;
while (current!=null){
if (current.vertexInfo.compareTo(v)==0){ //if it is the vertex u want to delete
if(current.vertexInfo.compareTo(head.vertexInfo)==0){ //if it is the head
head= current.nextVertex;
current=null;
}
else {
prev.nextVertex = current.nextVertex;
current=null;
}
return true;
} //end if
prev=current;
current= current.nextVertex;
} //end while
} //end else
return false;
} //end method
public ArrayList<T> DFS(T start_vertex){
ArrayList<T> list = new ArrayList<>();
ArrayList<Vertex<T,N>> visited_list = new ArrayList<>();
if(head==null)return list;
else if(!hasVertex(start_vertex)) return list;
//start Depth-First Search:
//First of all find the first vertex:
Vertex<T,N> temp_start = head;
while(temp_start!=null){
if(temp_start.vertexInfo.compareTo(start_vertex)==0)
break;
temp_start=temp_start.nextVertex;
}
Stack<Vertex<T,N>> hold = new Stack<>();
hold.push(temp_start); //hold first vertex to visit

while (!hold.isEmpty()){
visited_list.add(hold.pop()); //add top of the stack to the list
Edge<T,N> firstNeighbor = visited_list.get(visited_list.size()-1).firstEdge;
ArrayList<Vertex<T,N>> neighbors = new ArrayList<>(); //to hold the neighbors of each vertex
while (firstNeighbor!=null){ //if it has neighbors, then add them to neighbors arraylist
neighbors.add(firstNeighbor.toVertex);
firstNeighbor=firstNeighbor.nextEdge;
}
for(int x=0;x<neighbors.size();x++)//check if the neighbor not already in the visited list then add it to the stack
if(!visited_list.contains(neighbors.get(x))) hold.push(neighbors.get(x));
} //end while
for(int x=0;x<visited_list.size();x++){ //to get the vertices info
list.add(visited_list.get(x).vertexInfo);
}
return list;
//note: u can check if the search complete by checking if visited_list.size()==graph.getSize(), then it is completed
} //end method
public static void main(String[] args) {
Ready.Graph<String, Integer> graph1 = new Graph<>();
String[] cities = {"Alor Setar", "Kuching", "Langkawi", "Melaka", "Penang", "Tawau"};
for (String i : cities)
graph1.addVertex(i);

System.out.println("The number of vertices in graph1: " + graph1.getSize());

System.out.println("Cities and their vertices ");


for (int i = 0; i<=graph1.getSize()-1; i++)
System.out.print( i + ": " + graph1.getVertex(i) + "\t");
System.out.println();

System.out.println("Is Melaka in the Graph? " + graph1.hasVertex("Melaka"));


System.out.println("Is Ipoh in the Graph? " + graph1.hasVertex("Ipoh"));
System.out.println();

System.out.println("Kuching at index: " + graph1.getIndex("Kuching"));


System.out.println("Ipoh at index: " + graph1.getIndex("Ipoh"));
System.out.println();

System.out.println("add edge Kuching - Melaka: " + graph1.addEdge("Kuching", "Melaka", 800) );


System.out.println("add edge Langkawi - Penang : " + graph1.addEdge("Langkawi", "Penang", 100) );
System.out.println("add edge Melaka - Penang : " + graph1.addEdge("Melaka", "Penang", 400) );
System.out.println("add edge Alor Setar - Kuching : " + graph1.addEdge("Alor Setar", "Kuching", 1200) );
System.out.println("add edge Tawau - Alor Setar : " + graph1.addEdge("Tawau", "Alor Setar", 1900) );
System.out.println("add edge Kuching - Tawau : " + graph1.addEdge("Kuching", "Tawau", 900) );
System.out.println("add edge Langkawi - Ipoh : " + graph1.addEdge("Langkawi", "Ipoh", 200) );
System.out.println();

System.out.println("has edge from Kuching to Melaka? " + graph1.hasEdge("Kuching", "Melaka") );


System.out.println("has edge from Melaka to Langkawi? " + graph1.hasEdge("Melaka", "Kuching") );
System.out.println("has edge from Ipoh to Langkawi? " + graph1.hasEdge("Ipoh", "Langkawi") );
System.out.println();

System.out.println("weight of edge from Kuching to Melaka? " + graph1.getEdgeWeight("Kuching", "Melaka") );


System.out.println("weight of edge from Tawau to Alor Setar? " + graph1.getEdgeWeight("Tawau", "Alor Setar") );
System.out.println("weight of edge from Semporna to Ipoh? " + graph1.getEdgeWeight("Semporna", "Ipoh") );
System.out.println();

System.out.println("In and out degree for Kuching is " + graph1.getIndeg("Kuching") + " and " + graph1.getOutdeg("Kuching") );
System.out.println("In and out degree for Penang is " + graph1.getIndeg("Penang") + " and " + graph1.getOutdeg("Penang") );
System.out.println("In and out degree for Ipoh is " + graph1.getIndeg("Ipoh") + " and " + graph1.getOutdeg("Ipoh") );
System.out.println();

System.out.println("Neighbours of Kuching : " + graph1.getNeighbours("Kuching"));


System.out.println("\nPrint Edges : " );
graph1.printEdges();

graph1.removeVertex("Kuching");
System.out.println("\nPrint Edges : " );
graph1.printEdges();

}
Graph Traversals (Graph Search):
-The process of visiting (checking and/or updating) each vertex in a graph.
-Both traversals result in a spanning tree, which can be modeled using a class.
Two methods:
1- Depth-First Search:
- The search can start at any vertex.
- Algorithm:
1. Start by putting any one of the graph's vertices on top of a stack.
2. Take the top item of the stack and add it to the visited list.
3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the
visited list to the top of the stack.
4. Keep repeating steps 2 and 3 until the stack is empty.

- Applications of the DFS


-Detecting whether a graph is connected. Search the graph starting from any vertex. If the number
of vertices searched is the same as the number of vertices in the graph, the graph is connected.
Otherwise, the graph is not connected.
-Detecting whether there is a path between two vertices.
-Finding a path between two vertices.
-Detecting whether there is a cycle in the graph.
2- Breadth-First Search:
● With breadth-first traversal of a tree, the nodes are visited level by

level. First the root is visited, then all the children of the root, then the
grandchildren of the root from left to right, and so on.
Breadth-First Search
● Algorithm:
1. Start by putting any one of the graph's vertices at the back of a queue.
2. Take the front item of the queue and add it to the visited list.
3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the visited list to the back
of the queue.
4. Keep repeating steps 2 and 3 until the queue is empty.

● Applications of the BFS, similar to DFS, but:


– BFS able to find the path with smallest edges count (not weight/cost/distance) between 2 vertices.
– BFS can testing whether a graph is bipartite. A graph is bipartite if the vertices of the graph can be
divided into two disjoint sets such that no edges exist between vertices in the same set.
– BFS is inefficient in terms of memory consumption, compared to DFS.
Recursion
- Programming technique where a method calls itself. ( a method being called inside of itself).
- Also known as Self-Invocation
- Characteristics of Recursion:
- One or more base cases (the simplest case) are used to stop recursion.
- Recursive case: Every recursive call reduces the original problem, bringing it increasingly
closer to a base case until it becomes that case.
- To solve a problem using recursion, break it into subproblems that resemble the original
problem in nature but with a smaller size. Apply the same approach to solve the subproblem
recursively.
- Recursion is an alternative form of program control.
- repetition without a loop.
- substantial overhead –
- the system must assign space for all of the method’s local variables and parameters each
time a method is called.
- consume considerable memory and requires extra time to manage the additional space.
- However, it is good for solving the problems that are inherently recursive.
- You can return anything.
- Recursion: go find me the result of this and come back.
Computing Factorial

Let factorial(n) be the method for computing n!.


factorial(0) = 1;
factorial(n) = n*factorial(n-1);
1

2 3
Trace Recursive factorial
import java.util.Scanner;

public class ComputeFactorial {


/** Main method */
public static void main(String[] args) {
// Create a Scanner
Scanner input = new Scanner(System.in);
System.out.print("Enter a non-negative integer: ");
int n = input.nextInt();

// Display factorial
System.out.println("Factorial of " + n + " is " + factorial(n));
}

/** Return the factorial for a specified number */


public static long factorial(int n) {
if (n == 0) // Base case
return 1;
else
return n * factorial(n - 1); // Recursive call
}
}
Fibonacci Numbers

How do you find fib(index) for a given index? It is easy to find fib(2), because you know fib(0) and
fib(1). Assuming that you know fib(index - 2) and fib(index - 1), you can obtain fib(index) immediately.
Thus, the problem of computing fib(index) is reduced to computing fib(index - 2) and fib(index - 1).
When doing so, apply the idea recursively until index is reduced to 0 or 1.

The base case is index = 0 or index = 1. If you call the method with index = 0 or index = 1, it
immediately returns the result. If you call the method with index >= 2, it divides the problem into two
subproblems for computing fib(index - 1) and fib(index - 2) using recursive calls.
What happens if a recursive method never reaches a base case?
• Infinite recursion - occurs if recursion does not reduce the problem in a manner that allows it to eventually converge into
the base case
• The stack will never stop growing.
• But OS limits the stack to a particular height, so that no program eats up too much memory.
• If a program's stack exceeds this size, the computer initiates an exception (StackOverflowError), which typically would
crash the program.

What is the ouput?


public static long factorial(int n) {
return n * factorial(n - 1);
}
Output : The method runs infinitely and causes a StackOverflowError.
Recursion vs Iteration
• Recursion and loop are related concepts.
• Anything you can do with a loop, you can do with recursion, and vice versa.
• Sometimes recursion is simpler to write, and sometimes loop is, but in principle they are
interchangeable.

Recursion Iteration
– Terminate when a base case is reached – Terminates when a condition is proven to be false
– Each recursive call requires extra space on the – Each iteration does not require any extra space
stack frame (memory) – An infinite loop could loop forever since there is
– If we get infinite recursion, it may result in stack no extra memory being created
overflow
Directory (folder) Size
• A problem that is difficult to solve without using recursion.
• The size of a directory is the sum of the sizes of all files in the directory.
• A directory may contain subdirectories.
- The size of the directory can be defined recursively as follows:

import java.io.File;
import java.util.Scanner;

public class DirectorySize {


public static void main(String[] args) {
// Prompt the user to enter a directory or a file
System.out.print("Enter a directory or a file: ");
Scanner input = new Scanner(System.in);
String directory = input.nextLine();

// Display the size


System.out.println(getSize(new File(directory)) + " bytes");
}

public static long getSize(File file) {


long size = 0; // Store the total size of all files

if (file.isDirectory()) {
File[] files = file.listFiles(); // All files and subdirectories
for (int i = 0; files != null && i < files.length; i++) {
size += getSize(files[i]); // Recursive call
}
}
else { // Base case
size += file.length(); //if it is a file not a folder
}

return size;
}
}
Searching
Searching: locating a particular element value in the array. The common searching techniques
are Linear Search and Binary Search.

Linear search: This method works well for small arrays or for unsorted arrays. will search the
array one by one, so you use for loop.
- continues to do so until the key matches an element in the list or the list is exhausted without a match being
found.
- If found, returns the index of the element in the array that matches the key.
- If no match is found, the search returns -1.

public static int linearSearch(int[] list, int key) {


for (int i = 0; i < list.length; i++)
if (key == list[i])
return i;
return -1;
} //end method
Binary search: This method works well for large and sorted arrays. will divide
array into two half.
- first compares the key with the element in the middle of the group.
- If the key is less than the middle element, you only need to search the key in the first half
of the group.
- If the key is equal to the middle element, the search ends with a match.
- If the key is greater than the middle element, you only need to search the key in the second
half of the group.
public static int bs(int[] list, int key){
int low=0;
int high= list.length-1;
while (high>=low){
int mid = (low+high)/2;
if(key<list[mid]) high=mid-1;
else if(key==list[mid]) return mid;
else low = mid +1;
} //end while
return -1;
} //end method
Sorting
1- Selection sort: finds the smallest number in the list and places it first. It then
finds the smallest number remaining and places it second, and so on until the list
contains only a single number.
public static void selectionSort(double[] list) {
for (int i = 0; i < list.length - 1; i++) {
// Find the minimum in the list[i..list.length-1]
double currentMin = list[i];
int currentMinIndex = i;

for (int j = i + 1; j < list.length; j++) {


if (currentMin > list[j]) {
currentMin = list[j];
currentMinIndex = j;
} //end if
} //end nested for loop

// Swap list[i] with list[currentMinIndex] if necessary;


if (currentMinIndex != i) {
list[currentMinIndex] = list[i];
list[i] = currentMin;
} //end if
} //end for loop
} //method end
Other Selection Sort way:

public static void selectionSortSmallest(int[] arr){


int lab=0;
while (lab<arr.length){
int index_smallest_in_lab=lab; //start from the next index each time, in the beginning from 0
for(int y=lab; y<arr.length;y++) //get the smallest in this lab
if(arr[index_smallest_in_lab]>arr[y])
index_smallest_in_lab=y;
int hold= arr[lab];
arr[lab]=arr[index_smallest_in_lab];
arr[index_smallest_in_lab]=hold;
lab++; //go to the next lab, means ignore the first element in the second lab, and continue etc.
}//end while loop
} //end method
2- The insertion sort: algorithm sorts a list of values by repeatedly inserting an unsorted
element into a sorted sub list until the whole list is sorted.
public static void insertionSort(int[] list) {
for (int i = 1; i < list.length; i++) {
int currentElement = list[i];
int k;
for (k = i - 1; k >= 0 && list[k] > currentElement; k--)
list[k + 1] = list[k];
list[k + 1] = currentElement; // Insert the current element into list[k+1]
} //end for loop
} //end method
Other Insertion Sort way:

public static void Insertion_Sort(int[] input) {


for (int i = 1; i < input.length; i++) { //loop from the second element to the last element
for (int j = i; j > 0; j--) { //loop from the current element and go back to all elements behind
if (input[j] < input[j - 1]){ //check if the current element is smaller than the previous element then switch
int temp = input[j];
input[j] = input[j - 1];
input[j - 1] = temp;
}
} //nested for end
} //for end
}
3- Bubble Sort: make several passes through the array. On each pass, successive neighboring
pairs are compared. If a pair is in decreasing order, its values are swapped; otherwise, the
values remain unchanged.
- The smaller values gradually “bubble” their way to the top and the larger values “sink” to the
bottom.
- After the first pass, the last element becomes the largest in the array.
- After the second pass, the second-to-last element becomes the second largest in the array.
- This process is continued until all elements are sorted.

Array first way:


public static void bubbleSort(int[] list) {
boolean needNextPass = true;
for (int k = 1; k < list.length && needNextPass; k++) {
needNextPass = false;
for (int i = 0; i < list.length - k; i++) { Array second way: ArrayList:
if (list[i] > list[i + 1]) {
// Swap list[i] with list[i + 1] for(int x=0;x<input.length-1;x++){
int temp = list[i]; for(int y=0;y<input.length-x-1;y++){
list[i] = list[i + 1]; if(input[y]>input[y+1]){
list[i + 1] = temp; int hold=input[y];
needNextPass = true; // Next pass still needed input[y]=input[y+1];
} //end if input[y+1]=hold;
} //end nested for loop }
}//end for loop }
} // end method }
4- Merge Sort:
can be described
recursively as follows:
divides the array into two
halves and applies a
merge sort on each half
recursively. After the two
halves are sorted, merge
them.
/** The method for sorting the numbers */
public static void mergeSort(int[] list) {
if (list.length > 1) {

// Merge sort the first half


int[] firstHalf = new int[list.length / 2];
/*
public static void arraycopy(Object source_arr, int sourcePos, Object dest_arr, int destPos, int len)
- source_arr : array to be copied from
- sourcePos : starting position in source array from where to copy
- dest_arr : array to be copied in
- destPos : starting position in destination array, where to copy in
- len : total no. of components to be copied.
*/
System.arraycopy(list, 0, firstHalf, 0, list.length / 2);
mergeSort(firstHalf);

// Merge sort the second half


int secondHalfLength = list.length - list.length / 2;
int[] secondHalf = new int[secondHalfLength];
System.arraycopy(list, list.length / 2, secondHalf, 0, secondHalfLength);
mergeSort(secondHalf);

// Merge firstHalf with secondHalf into list


merge(firstHalf, secondHalf, list);
} //end if
} //end method

/** Merge two sorted lists */


public static void merge(int[] list1, int[] list2, int[] temp) {
int current1 = 0; // Current index in list1
int current2 = 0; // Current index in list2
int current3 = 0; // Current index in temp

while (current1 < list1.length && current2 < list2.length) {


if (list1[current1] < list2[current2]) temp[current3++] = list1[current1++];
else temp[current3++] = list2[current2++];
} //end while

while (current1 < list1.length) temp[current3++] = list1[current1++];

while (current2 < list2.length) temp[current3++] = list2[current2++];


// Breaks down the array to single or null elements in array.
private static int[] mergeSort(int[] array) {

Other way
if (array.length <= 1) return array; //base case

// Declare and initialize left and right arrays.


int midpoint = array.length / 2;

int[] left = new int[midpoint];


int[] right; Merge Sort
if (array.length % 2 == 0) right = new int[midpoint]; // if array.length is an even number.
else right = new int[midpoint + 1];

// give values to the left and right arrays.


for (int i = 0; i < midpoint; i++) left[i] = array[i];
for (int j = 0; j < right.length; j++) right[j] = array[midpoint + j];

int[] result = new int[array.length];

// Recursive call for left and right arrays.


left = mergeSort(left);
right = mergeSort(right);

// Get the merged left and right arrays.


result = merge(left, right);

// Return the sorted merged array.


return result;
} //end method

// Merges the left and right array in ascending order.


private static int[] merge(int[] left, int[] right) {

// Merged result array.


int[] result = new int[left.length + right.length];

// Declare and initialize pointers for all arrays.


int leftPointer=0, rightPointer=0, resultPointer=0;

// While there are items in either array...


while(leftPointer < left.length || rightPointer < right.length) {

// If there are items in BOTH arrays...


if(leftPointer < left.length && rightPointer < right.length) {

// If left item is less than right item...


if(left[leftPointer] < right[rightPointer])
result[resultPointer++] = left[leftPointer++]; //note: leftPointer++: will increase the leftPointer for the next round not this one.

else
result[resultPointer++] = right[rightPointer++];
}

// If there are only items in the left array...


else if(leftPointer < left.length)
result[resultPointer++] = left[leftPointer++];

// If there are only items in the right array...


else if(rightPointer < right.length)
result[resultPointer++] = right[rightPointer++];
}
return result;
}
The Efficiency of Algorithms
Measuring efficiency
● An algorithm has both time and space requirements, called its
complexity.
● we measure an algorithm’s :

– time complexity—the time it takes to execute


– space complexity—the memory it needs to execute
●But we will pay more attention to space complexity, since it is usually
more important.
Big O notation:
● Computer scientists use Big O notation to represent an algorithm’s complexity
● Instead of saying that Algorithm A has a time requirement proportional to n, we say

that A is O(n).
• In general, each node in a tree can have an arbitrary number of children. We
sometimes call such a tree a general tree. If each node has no more than n
children, the tree is called an n-ary tree.
• Not every general tree is an n-ary tree. If each node has at most two children,
the tree is called a binary tree.
Binary tree: is a hierarchical structure. It is either empty or consists of
an element, called the root, and two distinct binary trees, called the
left subtree and right subtree, either or both of which may be empty.
- Each node in a binary tree has zero, one, or two subtrees.

Terms:
• Length of path – number of edges in the path (eg:60-45 → 2)
• Depth – length of path from root to node (eg:60 → 0; 55→1)
• Level – set of all nodes at a given depth (e.g:55,100)
• Siblings – nodes share same parent node (eg: 45-57)
• Left child- root of the left subtree of a node
• Leaf – node without children (eg: A)
• Height – length of path fr root node to its furthest leaf (e.g 2)
Binary Search Tree
- A special type of binary tree called a binary search tree.
- It has no duplicate elements.
- The value in the left < the node < the value in the right.
- Representing Binary Trees:
A binary tree can be represented using a set of linked nodes. Each node contains a value and
two links named left and right that reference the left child and right child, respectively as
shown below.
- Create node:
• Variable root refers to the root node of the tree.
• If tree is empty, root is null.
• Create root node:
TreeNode<Integer> root = new TreeNode<Integer>(new Integer(60));
• Create left child node:
root.left = new TreeNode<Integer>(new Integer(55));
• Create right child node:
root.right = new TreeNode<Integer>(new Integer(100));
The Tree Interface
public interface Tree<E> extends Iterable<E> {
/** Return true if the element is in the tree */
public boolean search(E e);

/** Insert element o into the binary tree


* Return true if the element is inserted successfully */
public boolean insert(E e);

/** Delete the specified element from the tree


public abstract class AbstractTree<E> implements Tree<E>{
* Return true if the element is deleted successfully */
@Override /** Inorder traversal from the root*/
public boolean delete(E e);
public void inorder() {}
@Override /** Postorder traversal from the root */
/** Inorder traversal from the root*/
public void postorder() {}
public void inorder();
@Override /** Preorder traversal from the root */
public void preorder() {}
/** Postorder traversal from the root */
@Override /** Return true if the tree is empty */
public void postorder();
public boolean isEmpty(){return getSize() == 0;}
}
/** Preorder traversal from the root */
public void preorder();

/** Get the number of nodes in the tree */


public int getSize();

/** Return true if the tree is empty */


public boolean isEmpty();
}
Tree traversal: is the process of visiting each node in the tree exactly
once.
- There are several ways to traverse a tree:
• Inorder: visit the left subtree of the current node first recursively,
then the current node itself, and finally the right subtree of the current
node recursively.

• Postorder: visit the left subtree of the current node first, then the
right subtree of the current node, and finally the current node itself.

Two ways more in the next slide..


• Preorder (depth-first): visit the current node first, then the left subtree of the
current node recursively, and finally the right subtree of the current node
recursively.

• Breadth-first (level-order): visit the nodes level by level. First visit the root,
then all children of the root from left to right, then grandchildren of the root from
left to right, and so on.
For example, in the tree above,
the inorder is 45 55 57 59 60 67 100 101 107.
the postorder is 45 59 57 55 67 101 107 100 60.
the preorder is 60 55 45 57 59 100 67 107 101.
the breadth-first traversal is 60 55 100 45 57 67 107 59 101.
Deleting Elements in a Binary Search Tree
• Need to first locate the node that contains the element and also its parent
node.
• Let current point to the node that contains the element in the binary tree and
parent point to the parent of the current node.
• The current node may be a left child or a right child of the parent node.
There are two cases to consider:
Case 1: The current node does not have a left child, as shown in this figure (a).
Simply connect the parent with the right child of the current node, as shown in
this figure (b).
Case 2: The current node has a left child.
• Let rightMost point to the node that contains the largest element in the left subtree of the
current node and parentOfRightMost point to the parent node of the rightMost node, as
shown in next figure part (a).
• Note that the rightMost node cannot have a right child, but may have a left child.
• Replace the element value in the current node withn the one in the rightMost node,
connect the parentOfRightMost node with the left child of the rightMost node, and delete
the rightMost node, as shown in next figure part (b).
public class BST<E extends Comparable<E>>{

/** This inner class is static, because it does not access


any instance members defined in its outer class */
public static class TreeNode<E extends Comparable<E>> {
protected E element;
protected TreeNode<E> left;
protected TreeNode<E> right;
public TreeNode(E e) {element = e;}
public E getElement() { return element; }
}

protected TreeNode<E> root;


protected int size = 0;

public BST() {} //Create a default binary tree

/** Create a binary tree from an array of objects */


public BST(E[] objects) {for (int i = 0; i < objects.length; i++) insert(objects[i]);}

/** Get the number of nodes in the tree */


public int getSize() {return size;}

/** Returns the root of the tree */


public TreeNode<E> getRoot() {return root;}

/** Remove all elements from the tree */


public void clear() {
root = null;
size = 0;
}
/** Returns true if the element is in the tree */
public boolean search(E e){
TreeNode<E> current = root; // Start from the root
while (current != null){
if (e.compareTo(current.element) < 0) current = current.left;
else if (e.compareTo(current.element) > 0) current = current.right;
else return true; // element matches current.element then it is found
} //end while
return false;
}

/** Returns a path from the root leading to the specified element */
public java.util.ArrayList<TreeNode<E>> path(E e) {
java.util.ArrayList<TreeNode<E>> list = new java.util.ArrayList<TreeNode<E>>();
TreeNode<E> current = root; // Start from the root
while (current != null) {
list.add(current); // Add the node to the list
if (e.compareTo(current.element) < 0) current = current.left;
else if (e.compareTo(current.element) > 0) current = current.right;
else break;
} //end while
return list; // Return an array list of nodes
}
// Insert element into the binary tree Return true if the element is inserted successfully.
public boolean insert(E element) {
if (root == null) root = new TreeNode<E>(element); //if the tree is empty, then create a new root
else { // locate the parent node
TreeNode<E> parent = null;
TreeNode<E> current = root;
while (current != null) {
if (element.compareTo(current.element) < 0) { //less then go left
parent = current;
current = current.left;
} else if (element.compareTo(current.element) > 0) { //bigger then go right
parent = current;
current = current.right;
} else return false; // Duplicate node not inserted
} //end while
//now add the node:
if(element.compareTo(parent.element)<0)parent.left =new TreeNode<E>(element);//if element is less than the parent.
else parent.right = new TreeNode<E>(element); //if element is bigger than parent.
} //end else
size++;
return true; // Element inserted successfully
}
/** Returns the height of the tree*/
public int height(){ return height(root); }
/** Returns the height of the tree from giving node*/
private int height(TreeNode<E> node){
if (node == null) return -1;
return 1 + Math.max(height(node.left), height(node.right));
}

public E minValue() { return minValue(root); }


/* Function to return least value recursively */
private E minValue(TreeNode<E> node) {
if (node.left == null) return node.element;
return minValue(node.left);
}

public E maxValue(){return maxValue(root);}


/* Function to return least value recursively */
private E maxValue(TreeNode<E> node) {
if (node.right == null) return node.element;
return maxValue(node.right);
}
/** Inorder traversal from the root*/
public void inorder() {inorder(root);}

/** Inorder traversal from a subtree */


protected void inorder(TreeNode<E> root) {
if (root == null) return; //if tree is empty
inorder(root.left);
System.out.print(root.element + " ");
inorder(root.right);
}

/** Postorder traversal from the root */


public void postorder() { postorder(root); }

/** Postorder traversal from a subtree */


protected void postorder(TreeNode<E> root) {
if (root == null) return;
postorder(root.left);
postorder(root.right);
System.out.print(root.element + " ");
}

/** Preorder traversal from the root */


public void preorder() { preorder(root); }

/** Preorder traversal from a subtree */


protected void preorder(TreeNode<E> root){
if (root==null) return;
System.out.print(root.element + " ");
preorder(root.left);
preorder(root.right);
}

/** level-order traversal from the root */


public void level_order() {level_order(root);}

/** level-order traversal from a subtree */


protected void level_order(TreeNode<E> root){
if (root==null) return;
System.out.print(root.element+ " ");
preorder(root.left);
preorder(root.right);
}
/** Delete an element from the binary tree.
* Return true if the element is deleted successfully
* Return false if the element is not in the tree */
public boolean delete(E element) {
TreeNode<E> current = root; // Locate the node to be deleted
TreeNode<E> parent = null; //locate its parent node
while (current != null) {
if (element.compareTo(current.element) < 0) {
parent = current;
current = current.left;
}
else if (element.compareTo(current.element) > 0) {
parent = current;
current = current.right;
}
else break; // Element is in the tree pointed at by current
}

if (current==null) return false; // Element is not in the tree

if (current.left == null) { // Case 1: current has no left child


// Connect the parent with the right child of the current node
if (parent == null) root = current.right;
else {
if (element.compareTo(parent.element) < 0) parent.left = current.right;
else parent.right = current.right;
}
}

else { // Case 2: The current node has a left child


TreeNode<E> rightMost = current.left; // Locate the rightmost node in the left subtree of current node
TreeNode<E> parentOfRightMost = current; //locate its parent
while (rightMost.right != null) {
parentOfRightMost = rightMost;
rightMost = rightMost.right; // Keep going to the right
}

current.element = rightMost.element; // Replace the value in current by the value in rightMost

// Eliminate rightmost node


if (parentOfRightMost.right == rightMost) parentOfRightMost.right = rightMost.left;
else parentOfRightMost.left = rightMost.left; // Special case: parentOfRightMost == current
} //end else

size--;
return true; // Element deleted successfully
} //end delete
/** Obtain an iterator. Use inorder. */
public java.util.Iterator<E> iterator() { return new InorderIterator(); }

// Inner class InorderIterator


private class InorderIterator implements java.util.Iterator<E> {
// Store the elements in a list
private java.util.ArrayList<E> list=new java.util.ArrayList<E>();
private int current = 0; // Point to the current element in list

public InorderIterator(){inorder();} // Traverse binary tree and store elements in list

/** Inorder traversal from the root*/


private void inorder() { inorder(root); }

/** Inorder traversal from a subtree */


private void inorder(TreeNode<E> root) {
if (root == null)return;
inorder(root.left);
list.add(root.element);
inorder(root.right);
}

/** More elements for traversing? */


public boolean hasNext() {
if (current < list.size()) return true;
return false;
}

/** Get the current element and move to the next */


public E next() { return list.get(current++); }
/** Remove the current element */
public void remove() {
delete(list.get(current)); // Delete the current element
list.clear(); // Clear the list
inorder(); // Rebuild the list
}
} //end class InorderIterator

}
public static void main(String[] args) {
// Create a BST
BST<String> tree = new BST<String>();
tree.insert("George");
tree.insert("Michael");
tree.insert("Tom");
tree.insert("Adam");
tree.insert("Jones");
tree.insert("Peter");
tree.insert("Daniel");

// Traverse tree
System.out.print("Inorder (sorted): ");
tree.inorder();
System.out.print("\nPostorder: ");
tree.postorder();
System.out.print("\nPreorder: ");
tree.preorder();
System.out.print("\nThe number of nodes is " + tree.getSize());

// Search for an element


System.out.print("\nIs Peter in the tree? " + tree.search("Peter"));

// Get a path from the root to Peter


System.out.print("\nA path from the root to Peter is: ");
java.util.ArrayList<BST.TreeNode<String>> path = tree.path("Peter");
for (int i = 0; path != null && i < path.size(); i++)
System.out.print(path.get(i).getElement() + " ");

Integer[] numbers = {2, 4, 3, 1, 8, 5, 6, 7};


BST<Integer> intTree = new BST<Integer>(numbers);
System.out.print("\nInorder (sorted): ");
intTree.inorder();
}
Enum
Enumeration: list of values that doesn’t change but set up as a class and you can access it like a class.
- It does not have types, e.g.: String or int, it is just a labels, so to write a word you do not need quotation
marks.
- Better to write in upper case.
- to call a lable in enum, enumName.Lable , and it gonna print the lable.
- You can place enum out or inside the class.
- Can have methods inside the enum.

public class Main {


enum Level {
LOW, MEDIUM, HIGH;
}

public static void main(String[] args){


Level l = Level.LOW;
System.out.println(l); //print: LOW

switch (l){
case LOW -> System.out.println("It is low"); //print this
case MEDIUM -> System.out.println("It is medium");
case HIGH -> System.out.println("It is High");
}

enum LowerLevel{ //inner enum


LOWLOW, LOWMID,LOWHIGH;

public static void print_lowest(){ //can have methods inside


System.out.println(LowerLevel.LOWLOW);
}
} //enum ends

} //main method ends

} //class ends
HashMap
HashMap: list of keys and for each key there is a value.
- Hashmap can be raw type or it can have <Key_Type,Value_Type>.
- HashMaps do not have an order.
- Methods:
- put(key,value);
- get(key);
- remove(key);
- containsValue(value);
- containsKey(key);
- size();
- replace(key,newValue);
- values(); //print the values.
- ketSet(); //print the keys.

public static void main(String[] args) {


HashMap <String,Integer> h = new HashMap();
h.put("A",1);
h.put("B",2);
}
HashSet
HashSet: list of values.
- HashSet can be raw type or it can have <Values_Type>.
- HashSet do not have an order.
- Methods:
- add(value);
- remove(value);
- clear();
- size();
- contains(value);
- isEmpty();

public static void main(String[] args) {


HashSet<Integer> h = new HashSet();
h.add(1);
h.add(2);
Iterator<Integer> i = h.iterator();
while(i.hasNext())
System.out.println(i.next());
}
Lambda expression
- known as an anonymous method a shorter way to write anonymous classes with one method.
- To use the lambda: u need to use a functional interface or use a pre-defined functional interface, they contain only one
abstract method, examples of interfaces: ActionListener, Runnable, (user-defined).
- Syntax: (arguments) -> {statements};
- if the body is just one line then u can remove the brackets.

- User-defined interface with a method with an empty parameter:


@FunctionalInterface
public interface MyInterface { //user-defined a functional interface
public void message();
}

public class Main {


public static void main(String[] args) {
MyInterface myInterface = () -> System.out.println("hello"); //the argument is empty, coz the method does not have a parameter.
myInterface.message();
}
}

- User-defined interface with a method with a parameter: - User-defined interface with a method with two parameters:

@FunctionalInterface @FunctionalInterface
public interface MyInterface { //user-defined a functional interface public interface MyInterface { //user-defined a functional interface
public void message(String name); public void message(String name, char symbol);
} }

public class Main { public class Main {


public static void main(String[] args) { public static void main(String[] args) {
String name = "MAJD"; String name = "MAJD";
MyInterface myInterface = (x) -> { //the argument is a x, which is a String variable char symbol ='?';
System.out.println("hello"); MyInterface myInterface = (x,y) -> { //the argument is a x, which is a String variable
System.out.println("How can I help u "+x); System.out.println("hello");
}; System.out.println("How can I help u "+x+y);
myInterface.message(name); };
} myInterface.message(name,symbol);
} }
}
-Pre-defined interface (ActionListener):
import javax.swing.*;

public class MyFrame extends JFrame {


JButton myButton = new JButton("My Button");

MyFrame(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(420,420);
this.setLayout(null);
this.setVisible(true);

myButton.setBounds(100,100,200,100);
this.add(myButton);

//for the button to preform an action:

//before:
/*
myButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("U clicked the button!");
}
});
*/

//Using lambda expression, because ActionListener interface has only one abstract method
myButton.addActionListener((e) -> System.out.println("U clicked the button!"));

public class Main {


public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
}
}
The double colon (::) operator, also known as method reference operator, is
used to call a method by referring to it with the help of its class directly. They behave exactly
as the lambda expressions. The only difference it has from lambda expressions is that this
uses direct reference to the method by name instead of providing a delegate to the method.

1- Static method
- Syntax: (ClassName::methodName)
2-Instance method
- Syntax: (objectOfClass::methodName)
3- Super method
- Syntax: (super::methodName)
4- Class Constructor
Syntax: (ClassName::new)
How to add an External library to the project in IntelliJ:
1. Download the library as jar file.
2. Click File from the toolbar.
3. Select Project Structure option (CTRL + SHIFT + ALT + S (shortcut on
Windows)).
4. Select Modules at the left panel.
5. Select Dependencies tab.
6. Select + icon.
7. Select 1 JARs or directories option.

You might also like