0%

COSI 12B Java Programming

Lecture 01 2021/08/30

  1. Java Basics
    • Everything is inside classes, classes contain methods, there are statements inside the methods
    • There should be a main method inside the public class
    • Example
      1
      2
      3
      4
      5
      6
      public class MyProgram {
      public static void main(String[] args) {
      // System is a class, out is the object, println is the method
      System.out.println("Hello world!");
      }
      }
    • Comments
      • Inline comments
      • Multiline comments
      • Javadoc style comments
    • Steps for execution of java programs: java source file -> compiler -> ava byte code in class file-> interpreter translates bytecode into machine language in JRE and executes it
      • Commands to compile the source file: javac MyProgram.java
      • Commands to run the byte code: java MyProgram
    • Printing
      • System.out.println();
      • System.out.print();
      • System.out.printf("format string", <list parameters>);
        • %d, %W.Df W characters wide, D digits after decimal, %Ws W length, right justified, %-Ws W length, left justified
        • %b: boolean, %s: string, %S: uppsercase string, %d: base 10 integer, %o: base 8 integer, %x: base 16 integer, %X: base 16 integer in uppercase, %e: scientific float, %E: scientific float with Es
  2. Variables and Data Types
    • A variable is a name for a location in memory
    • Variable declaration, variable initialization
    • Primitive types: byte, boolean, short, character, integer, long, float, double
    • String concatenation operator plus has the same priority as arithmetic plus
  3. Interactive Programs
    • The Scanner class is used to get input from the user, allowing a program to be interactive
    • It's par of the java.util package
    • Scanner objects can read input from many sources
    • Demo
      1
      2
      3
      4
      5
      6
      7
      8
      9
      import java.util.*;

      public class Test {
      public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      int anInteger = scanner.nextInt();
      System.out.println(anInteger);
      }
      }
    • nextInt(), nextDouble(), next(), nextLine();
    • If there is EOF but you call next method, then there is java.util.NoSuchElementException
  4. Control Statements
    • Conditional statements
      1
      2
      3
      4
      5
      6
      7
      if (condition) {
      statements;
      } else if {
      statements;
      } else {
      statements;
      }
    • Repetition Statements
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // for indefinite loops
      while (condition) {
      statements;
      }

      for (initialization; condition; increment) {
      statements;
      }
      // the body is guaranteed to execute at least once
      do {
      statements;
      } while (condition);

Lecture 02 2021/09/01

  1. Static Methods
    • Method declaration: method header, method body
    • public static void main(String[] args)
  2. Strings
    • Strings are immutable, a string is an object storing a sequence of characters
    • str.length(), the length is a method
    • str.charAt(index): returns a character in [0, str.length() - 1], otherwise IndexOutOfBoundsException
    • str.substring(start): start is inclusive, returns a substring from [start, str.length() - 1], IndexOutOfBoundsException if start < 0 or start > length
    • str.substring(start, end): start is inclusive, end is exclusive, IndexOutOfBoundsException if start < 0, or end > length, or start > end
    • str.toLowerCase(): returns a string
    • str.toUpperCase(): returns a string

Lecture 03 2021/09/13

  1. Strings
    • String is reference type, char is primitive type
    • You can compare char with ==, !=
    • Each char is mapped to an int value, called the ASCII value
      • (int)'a' = 97, (int)'A' = 65
    • Mixing int and char causes automatic conversion to int
    • To convert an int into the equivalent char, type-cast it
    • str1.equals(str2),use equals method to compare Objects
  2. Random Numbers
    • Pseudorandom numbers are derived from predicable and well-defined algorithms
    • Math.random(): returns a random double numebr in [0,1), Math class is in the java.lang package, so there is no need to import that class
    • Random class
      • import java.util.Random;
      • Random.nextInt(): returns a random integer between \(2^{-31}\) to \((2^{31} - 1)\)
      • Ranxom.nextInt(max): returns a random integer in the range [0, max), in other wrods, 0 to max - 1 inclusive
      • Random.nextDouble(): returns a random real number in the range [0.0, 1.0)
      • Random.nextBoolean(): returns a random logical value of true or false
  3. File Processing
    • File Object
      • import java.io.File;
      • File file = new File("pathName");
      • file.getName(), file.exists(), file.getParent(), file.length(), file.canRead(), file.isFile(), file.isDirectory(), file.renameTo(fileName)
    • File with Scanner
      • Add throws clause to your code because: public Scanner(File source) throws FileNotFoundException
      • Demo
        1
        2
        3
        4
        public static void main(String[] args) throws FileNotFoundException {
        // This Scanner method throws FileNotFoundException
        Scanner fileScanner = new Scanner(new File("pathName"));
        }
    • Exceptions
      • An exception is an error that occurs at runtimme as a result of some tpe of exceptional circumstance
      • Example:
        • java.io.FileNotFoundException
        • java.lang.StringIndexOutOfBoundsException, java.lang.StringIndexOutOfBoundsException
        • java.lang.IllegalArgumentException
        • java.util.NoSuchElementException
        • java.lang.NullPointerException
      • Exception Inheritance:
        • Throwable -> Error/Exception; Exception ->RuntimeException/Other Exceptions
        • Unchecked exceptions: Error/RuntimeException
        • Checked exceptions: Other exceptions, you need either throw or catch each checked exception
      • The complier checks you either declare that you don't handle it(throws clause) or you handle or fix it(try/catch)
    • Token-based vs line-based processing
      • Token: unit of user input, separated by whitespace
      • Consuming input means reading input and advancing the cursor
    • Scanner Object
      • hasNext(): returns true if there is a next token
      • hasNextInt(): returns true if there is a next token and it can be read as an int
      • hasNextDouble(): returns true if there is a next token and it can be read as a double
      • nextLine(): returns next entire line of input
      • hasNextLine(): returns true if there are any more lines of input to read
    • Read line by line
      1
      2
      3
      4
      5
      6
      7
      8
      9
      public static void main(String[] args) throws FileNotFoundException {
      Scanner fileScanner = new Scanner(new File("pathname"));

      while (fileScanner.hasNextLine()) {
      String line = fileScanner.nextLine();
      Scanner lineScanner = new Scanner(line);
      // Process the line
      }
      }
    • File Output
      • import java.io.PrintStream;
      • Add throws clause to your code because: public PrintStream(File file) throws FileNotFoundException. If the file exists, then it will be truncated to zero size; otherwise, a new file will be created
      • Example
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        public static void main(String[] args) throws FileNotFoundException {
        Scanner fileScanner = new Scanner(new File("pathname"));
        PrintStream output = new PrintStream(new File("pathname"));

        while (fileScanner.hasNext()) {
        String line = fileScanner.nextLine();
        String lineResult = "";
        // Process the line into lineResult
        writer.println(lineResult);
        }
        }
      • When you do not have permisson to write in the target directory, or when the file is used by another file, Exceptions are caused

Recitation 01 2021/09/13

  1. Debugging
    • Some common uses for debugging
      • Investigating variable values
      • Pinpointing bugs
      • Walking through code one line at a time
    • How to debug
      • Use print statement
      • Use debugger in IDE
  2. String
    • isPalindrome practice
      1
      2
      3
      4
      5
      6
      7
      8
      9
      public static boolean isPalindrome(String input) {
      int n = input.length();
      for (int i = 0; i < n / 2; i++) {
      if (input.charAt(i) != input.charAt(n - 1 - i)) {
      return false;
      }
      }
      return true;
      }
  3. Random
    • RollDice practice
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      public static int rollDice(int n, int target) {
      if (target < n || target > 6 * n) {
      return -1;
      }

      int cnt = 0;
      int cur = 0;
      Random random = new Random();
      while (cur != target) {
      for (int i = 0; i < n; i++) {
      int val = random.nextInt(6) + 1;
      cur += val;
      }
      cnt += 1;
      }

      return cnt;
      }
  4. File Processing
    • printDuplicate practice
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      public static void scanFile(String filename) throws FileNotFoundException {
      Scanner file = new Scanner(new File(filename));
      PrintStream output = new PrintStream(new File("./src/output.txt"));
      while (file.hasNextLine()) {
      String line = file.nextLine();
      Scanner scan = new Scanner(line);
      int prev = -1;
      int cur = -1;
      int count = 1;
      while (scan.hasNextInt()) {
      cur = scan.nextInt();
      if (prev == cur) {
      count += 1;
      } else {
      if (count > 1) {
      output.print(prev + " * " + count + " ");
      }
      prev = cur;
      count = 1;
      }
      }
      if (count > 1) {
      output.print(prev + " * " + count + " ");
      }
      output.print("\n");
      scan.close();
      }
      file.close();
      }

Lecture 04 2021/09/15

  1. Arrays
    • An array is a collection (object) of data values (or elements) of the same type
    • Create an array
      1
      2
      3
      4
      5
      6
      7
      8
      int[] arr1 = new int[5];
      for (int i = 0; i < 5; i++) {
      arr[i] = i;
      }

      int[] arr2 = new int[] {0, 1, 2, 3, 4};

      int[] arr3 = {0, 1, 2, 3, 4};
    • length is an attribute: arr.length
    • Auto initialization: zero-equivalent value: 0 for int, 0.0 for floating number, false for boolean, null for Object, \0 for char
    • Limitations of array:
      • import java.util.Arrays;
      • Cannot resize existing array
      • Cannot print an array directly, use System.out.println(Arrays.toString(arr));
      • Cannot compare arrays directly, use System.out.println(Arrays.equals(arr1, arr2));
    • Tool Class: java.util.Arrays
  2. Primitive and Reference Types
    • Primitive types: byte, boolean, short, char, int, long, float, double,
    • Primitive type variable stores one value at a time, reference type variable(called reference) stores the location of an object in the memory
    • Copy references: when you assign one reference to another, you are simply copying the reference to the object, so modifying the value of one variable affects another
    • Objects(Arrays) are passed as parameters by reference

Lecture 05 2021/09/20

  1. Array Objects vs String Objects
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      int[] arr1 = {1,2,3};
      int[] arr2 = {1,2,3}
      arr1 == arr2; // false
      Arrays.equals(arr1, arr2); // true
      String s1 = "abc"; // in the String constant pool
      String s2 = "abc"
      String s3 = new String("abc"); // in the heap memory
      String s4 = String.valueOf("abc"); // in the String constant pool
      s1 == s2 // true
      s1 == s3 // false
      s1 == s4 // true
    • String constant pool is a separate place in the heap memory, duplicates are not allowed
    • s1.concat(s2): returns a new string
    • Null reference
      • To indicate that a reference variable doesn’t yet refer to any object, we can assign it a special value called null
      • java.lang.NullPointerException
    • Find algorithm on array should return index instead of the object itself

Recitation 02 2021/09/20

  1. Array
    • shiftArray
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public static void shiftArray(int[] arr) {
      int lo = 0;
      int hi = arr.length - 1;
      while (lo < hi) {
      if (arr[lo] % 2 == 0) {
      lo += 1;
      } else {
      if (arr[hi] % 2 == 0) {
      int temp = arr[hi];
      arr[hi] = arr[lo];
      arr[lo] = temp;
      lo += 1;
      hi -= 1;
      } else {
      hi -= 1;
      }
      }
      }
      }
  2. Not contained in Recitation, but in books
    • Arrays
      • Arrays.toString(): returns a string
      • Arrays.sort(arr, new MyComparator()): void return type
      • Arrays.copyOf(oldArr, newLength): returns a new array, empty slots are filled with zero equivalent values
      • Arrays.equals(arr1, arr2)
      • Arrays.copyOfRange(oldArr, oldStartIndex, oldEndIndex): startIndex is inclusive, endIndex is exclusive
    • For each loop
      1
      2
      3
      4
      5
      6
      7
      for (int i = 0; i < arr.length; i++) {
      System.out.println(arr[i]);
      }

      for (int num: arr) {
      System.out.println(num);
      }

Lecture 06 2021/09/22

  1. Array Reversal In Place
    1
    2
    3
    4
    5
    6
    7
    8
    public static void reverse(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n / 2; i++) {
    int temp = arr[i];
    arr[i] = arr[n - 1 - i];
    arr[n - 1 - i] = temp;
    }
    }
  2. LinkedList Reversal
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static Node reverse(Node head) {
    Node re = null;
    Node front = head;
    while (front != null) {
    Node temp = front.next;
    front.next = re;
    re = front;
    front = temp;
    }
    return re;
    }
  3. mostFrequentDigit
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static int mostFrequentDigit(int value) {
    int digits = new int[10];
    while (value != 0) {
    int digit = value % 10;
    digits[digit] += 1;
    value /= 10;
    }
    int index = 0;
    for (int i = 0; i < 10; i++) {
    if (digits[i] > digits[index]) {
    index = i;
    }
    }
    return index;
    }
  4. Multidimensional Array
    • 2D array: int[][] arr = new int[a][b];
      • nrow: int nrow = arr.length;
      • ncol: int ncol = arr[0].length;
      • You can have different ncols: int[][] arr = new int[a][];
  5. Bubble Sort
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static void bubbleSort(int arr[]) {
    int n = arr.length;
    for (int i = 0; i < n; i++) {
    for (int j = 0; j < n-i-1; j++){
    if (arr[j] > arr[j+1]) {
    int temp = arr[j];
    arr[j] = arr[j + 1];
    arr[j + 1] = temp;
    }
    }
    }
    }
  6. Class and Objects
    • Procedural programming and Object-oriented programming
    • Objects contain both variables and methods
    • Object: An object is a programming entity that has state (data) and behavior (methods)
    • State: A state is a set of values (internal data) stored in an object
    • Behavior: A behavior is a set of actions an object can perform, often reporting or modifying its internal state

Lecture 07 2021/09/29

  1. Wrapper Classes
    • Categories: all classes are inside java.lang package, so no need to import them

      Primitive Type Wrapper Class
      byte Byte
      short Short
      char Character
      int Integer
      long Long
      double Double
      float Float
      boolean Boolean
    • Autoboxing and unboxing

      1
      2
      3
      4
      // Integer val = Integer.valueOf(5);
      Integer val = 5;
      // int val = val.intValue();
      int value = val;

    • Range: If boolean, byte, char <= 127, or if -128 <= short, int <= 127, the boxed value are unique

      1
      2
      3
      4
      5
      6
      7
      Integer val1 = 127;
      Integer val2 = 127;
      System.out.println(val1 == val2); // true
      val1 += 1;
      val2 += 1;
      System.out.println(val1 == val2); // false
      System.out.println(val1.equals(val2)); //true

    • Convert string into other type: int value = Integer.parseInt("string", intBase), convert integer string into int value with basis intBase

    • Convert other type into string: String result = Integer.toString(intVal, intBase), convert an int value into integer string with basis intBase

    • Character API

      • public static boolean isLetter(char ch)
      • public static boolean isDigit(char ch)
      • public static char toUpperCase(char ch)
      • public static char toLowerCase(char ch)
  2. Classes and Objects
    • Class: A class is like a blueprint (defined by the user) for which objects are created. It is a definition of a new type of objects
    • Instantiation syntax: Point point = new Point(x, y);
    • Access and modify fields:
      • Access: int x = point.x;
      • Modify: point.x = xValue;
    • Client code: A client code is the code that interacts with a class or objects of that class
    • Instance method: An instance method (or object method) is a method that exists inside each object of a class and gives behavior to each object
      • Calling an instance method: curPoint.translate(dx, dy);

Lecture 08 2021/10/04

  1. Classes and Objects
    • Static Methods vs Instance Methods

      Static Method Instance Method
      Can be called without creating an object of class Require an object of its class before it can be called
      Declared with static keyword Do not have static keyword
      Exist as a single copy for the class Each instance of the class has a copy
      Cannot access instance methods and instance variables directly Can access static methods and static variables directly
    • Implicit parameter: An implicit parameter is the object on which an instance method is called

    • toString() method:

      • When a Java program is printing an object or concatenating an object to a String, it calls the toString method
      • The toString method tells Java how to convert an object into a String
      • toString simply returns a String that the client can use in a println statement, it does not contain print statements itself
    • Constructor

      • A constructor initializes the state of a new object
      • No return type is specified
      • A class can have multiple constructors, each must have different parameters(must have a different signature), you can call one constructor in another one using this keyword
      • If user-defined constructors are not provided, a default constructor without any argument will be provided by Java
      • Demo
        1
        2
        3
        4
        5
        6
        7
        8
        public Point(int x, int y) {
        this.x = x;
        this.y = y;
        }

        public Point() {
        this(0, 0);
        }
      • Mutators and Accessors
        • Mutator: A mutator is an instance method that modifies the object’s internal state
        • Accessor: An accessor is an instance method that provides information about the state of an object without modifying it
        • Demo
          1
          2
          3
          4
          5
          6
          7
          8
          // accessor method
          public int getX() {
          return this.x;
          }
          // mutator method
          public void setX(int x) {
          this.x = x;
          }

Recitation 03 2021/10/04

  1. JUnit
  2. Array
    • Triangle
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public static int[][] triangle(int n) {
      int[][] arr = new int[n][];
      for (int i = 0; i < n; i++) {
      arr[i] = new int[i + 1];
      arr[i][0] = 1;
      arr[i][arr[i].length - 1] = 1;
      }
      for (int i = 0; i < n; i++) {
      for (int j = 0; j < i + 1; j++) {
      if (j != 0 && j != i) {
      arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
      }
      }
      }
      return arr;
      }
    • Meeting
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public static int[] meeting(int[][] a, int[][] b, int dur) {
      int[] result = new int[2];
      for (int i = 0; i < a.length; i++) {
      for (int j = 0; j < b.length; j++) {
      int lo = Math.max(a[i][0], b[j][0]);
      int hi = Math.min(a[i][1], a[j][1]);
      if (hi - lo >= dur) {
      result[0] = lo;
      result[1] = lo + dur;
      return result;
      }
      }
      }
      return null;
      }

Lecture 09 2021/10/06

  1. equals() method
    • The == operator compares references to objects and only evaluates to true if two variables refer to the same object, it does not tell us whether two objects have the same state
    • The equals method compares the state of objects, the default equals method acts just like the == operator, we need to replace it when needed
    • The parameter to a proper equals method must be of type Object
    • Signature public boolean equals(Object o)
    • Type-casting
      • For type-casting with primitive types, we convert one type to another
      • For type-casting with objects, we actually cast a reference into another
      • The instanceof keyword
        • Syntax: variable instanceof type
    • Template for equals() method
      1
      2
      3
      4
      5
      6
      7
      8
      public boolean equals(Object o) {
      if (o instanceof T) {
      T other = (T) o;
      // do comparison here
      // return a boolean value here
      }
      return false;
      }
  2. this keyword
    • Variable shadowing: when a variable declared within a certain scope has the same name as a variable declared in an outer scope. This outer variable is said to be shadowed by the inner variable
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      public class Shadow {
      private int myIntVar = 0;

      public void shadowTheVar() {
      // Since it has the same name as above object instance field, it shadows above
      // field inside this method.
      int myIntVar = 5;

      // If we simply refer to 'myIntVar' the one of this method is found
      // (shadowing a second one with the same name)
      System.out.println(myIntVar); // prints 5

      // If we want to refer to the shadowed myIntVar from this class we need to
      // refer to it like this:
      System.out.println(this.myIntVar); // prints 0
      }

      public static void main(String[] args){
      new Shadow().shadowTheVar();
      }
      }
    • Use this to eliminate confusion
      • Refer to a field: this.field;
      • Call a method: this.method(parameters);
      • Call a constructor: this(parameters)
    • In terms of class constructor, using this keyword and variable shadowing is preferred
  3. Arrays of Objects
    • When objects are first constructed, their fields are initialized to their default value
      • Primitive types are initialized to 0-equivalent values
      • Objects are initialized to null
    • null: it is a value that indicates that the object reference is not currently referring to an object
      • The elements of an array of objects are initialized to null
    • Dereferencing
      • Definition: the ability to reference something using a name, reference, or container instead of the value itself
      • In java, deferencing happens when using . operator
      • If follows the memory address placed in a reference to the place in memory where the actual object is located
      • If you dereference null, NullPointerException will be caused

Lecture 10 2021/10/11

  1. Method Overloading
    • Method overloading: a feature that allows a class to have more than one method with the same name but different argument lists
      • The modifier, the return type should be the same, the argument type, argument order and argument amount can be different
      • Constructor overloading allows a class to have more than one constructor with different arguement lists
    • Type promotion
      • A data type of smaller size is promoted to the data type of bigger size
      • Java allows automatic type promotion
        1
        2
        3
        4
        5
        public calcRate(double amount, double rate) {
        return amount * rate / 100;
        }

        calcRate(100,4); // 4.0
    • Method overloading has risk, if wrong arguments are passed in, there will be compile erros
      • This one works:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        public calcRate(double amount, int rate) {
        return amount * rate / 100;
        }

        public calcRate(int amount, int rate) {
        return amount * 1.0 * rate / 100;
        }

        calcRate(100, 4); // 4.0, the second method is called
      • This one does not work:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        public calcRate(double amount, int rate) {
        return amount * rate / 100;
        }

        public calcRate(int amount, double rate) {
        return amount * rate / 100;
        }

        calcRate(100, 4); // compile error, the computer does not which method to call
    • The final keyword for parameters
      • If a parameter is defined with final, then it is meant not to be changed inside the method and is considered a constant within the method
      • a method with final and a method without final are not overloading methods, they are considered to be the same function
        1
        2
        3
        // the following two methods are considered to be the same
        public double calcRate(final int balance, double rate);
        public double calcRate(int balance, double rate);
  2. Encapsulation
    • Definition: refers to the concepts of hiding implementation details of an object from the clients of the object

    • Benefits:

      • Protect the integrity of an object's data
      • Focus on external behavior while ignoring the details of inner workings
    • Four OOP concepts

      • Encapsulation
      • Inheritance
      • Polymorphism
      • Abstraction
    • private fields

      • Private fields cannot be accessed from outside the class, it's only visible to all code inside its class
      • Private fields are usually accessed by getter and setter methods, getters are used to retrieve fields, setters are used to modify fields
    • Class invariant

      • It's an assertion about an object's state that is true thoughout the lifetime of the object
      • An invariant can be thought of as a postcondition on every constructor and mutator method of a class
    • Preconditions and postconditions

      • Precondition: something that you assume to be true when your method is called
      • Postcondition: something you promise to be true when you method exits
      • When conditions, you can throw an exception
        • Syntax: throw nex Exception(); or throw new Exception("message");
    • Variables comparison

      Local Variables Instance Variables Static(Class) Variables
      Declared locally in methods, constructors, or blocks Declared nonlocally in class Declared nonlocally with static keyword in class
      Created when local scope is entered, destroyed when local scope is exited Created when an object is created, destroyed when the object is destroyed Created when the program starts and destroyed when the program stops
      Local scope visibility Usually private, cannot be accessed by the class user Usually public, can be accessed by the class user
      No default value Can have default values Can have default values
      Called using object.field Called using Class.field

Lecture 11 2018/10/13

  1. Inheritance
    • Inheritance is an important concept of OOP and promotes software reusability
    • It allows a software developer to derive a new class from an existing one
      • The existing class is the parent class, superclass or base class
      • The derived class is the child class or subclass
    • UML class diagram: subclass points to superclass
    • Is-a relationship: it is a hierarchical connection where one category can be treated as a specialized version of another
    • Inheritance hierarchy is a set of classes connected by is-a relationship that can share common code
    • Syntax: public class A extends B
    • Override: to write a new version of a method in a subclass that replaces the superclass's version
      • Call overridden methods: super.method(parameters)

      • If a method is declared with the final modifier, it cannot be overridden

        Overloading Overriding
        One class contains multiple methods with same name but different parameter signatures a subclass substitutes its own version of an otherwise inherited method, with the same name and the same parameters
        Same visibility modifier, return type, method name Same visibility modifier, method name, parameters
        Different parameters(parameter amount, parameter order, parameter type) Return type can be different
        Similar operations in different ways for different data Similar operation in different ways for different object types

Lecture 12 2021/10/18

  1. Inheritance
    • super keyword
      • Subclass can call overridden methods with the super keyword: super.method(parameters)
      • Constructors are not inherited, the first line of a child's constructor should use the super reference to call the parent's constructor
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        public class Employee {
        private String name;
        private int age;
        public Employee() {
        this.name = "Jesse";
        this.age = 20;
        }

        public Employee(String name, int age) {
        this.name = name;
        this.age = age;
        }
        }

        public class Secretary extends Employee {
        public Secretary() {
        super();
        }

        public Secretary(String name, int age) {
        super(name, age);
        }
        }
    • private data from superclass cannot be accessed from subclass, subclass has to use getter/setter methods
    • protected keyword
      • Provides intermediate level of security between public and private access
      • Allows a member of superclass to be inherited into a subclass
    • Polymorphism: ablity for an object to be used as if it was of different type
      • Example
        1
        2
        3
        4
        5
        6
        7
        Employee[] employees = new Employee[2];

        Employee var1 = new Laywer();
        Employee var2 = new Boss();

        employees[0] = var1;
        employees[1] = var2;
    • The Object class
      • The Object class is the parent class of all classes in Java
      • It is inside the java.lang package
      • If a class is not explicitly defined as a child class of an existing class, then it is the child class of the Object class
      • toString() method
        • Default one in Object class
          1
          2
          3
          public String toString() {
          return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
          }
        • You should override this method in your class
      • equals() method
        • Default one in Object class
          1
          2
          3
          public boolean equals(Object obj) {
          return this == obj;
          }
        • You should override this method in your class
  2. Object Casting
    • Upcasting: an object of a subclass type can be treated as an object of any superclass type, upcasting is automatic in Java, it's implicit casting
    • Downcasting: treate a supercalss object as its real subclass, downcasting must be specified, it's explicit casting
    • By casting an object, you are not actually changing the object itself, you are just labeling it differently
    • Upcasting can never fail, but for downcasting, you need to specify which subclass you want to cast into
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      public class Mammal{}
      public class Cat extends Mammal{}
      public class Dog extends Mammal{}

      Mammal mammal = new Mammal();
      Cat cat = (Cat) mammal; // java.lang.ClassCastException

      Mammal mammal = new Cat();
      Cat cat = (Cat) mammal; // this one works
  3. Initialization Order
    • Order
      1. Static fields and static blocks of ancestors, in the order of appearance
      2. Static fields and static blocks of instantiated class, in the order of appearance
      3. Instance fields and initialization blocks of ancestors, in the order of appearance
      4. Constructor of ancestors
      5. Instance fields and initialization blocks of instantiated class, in the order of appearance
      6. Constructors of instantiated class
    • Fields are not overriding, constructors are not overriding, only methods are
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      class Ancestor {
      int x = 10;

      public Ancestor() {
      this.print();
      x = 20;
      }

      public void print() {
      System.out.println("Ancestor.x: " + x);
      }
      }

      class Child1 extends Ancestor {
      int x = 30;

      public Child1() {
      this.print();
      x = 40;
      }

      public void print() {
      System.out.println("Child1.x: " + x);
      }
      }

      class Child2 extends Ancestor {
      int x = 40;

      public Child2() {
      this.print();
      x = 50;
      }
      }

      public class Test {
      public static void main(String[] args) {
      Ancestor ch1 = new Child1(); // Child1.x 0; Child1.x 30;
      System.out.println(ch1.x); // 20

      Ancestor ch2 = new Child2(); // Ancestor.x 10; Ancestor.x 20
      System.out.println(ch2.x); // 20
      }
      }

Lecture 13 2021/10/20

  1. Polymorphism
    • Polymorphism indicates the ability for the same code to be used with different types of objects and behave differently with each
    • Syntax: Superclass var = new Subclass();
      • You can call all methods in superclass, the left side static type limits the scope of methods you can call on var
      • You cannot call any method that only exists in subclass
      • For overridden methods, the one defined in subclass is called, the right side dynamic type specifies which version of overridden methods is called
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      public class Snow {
      public void method2() {
      System.out.println("Snow 2");
      }
      public void method3() {
      System.out.println("Snow 3");
      }
      }

      public class Rain extends Snow {
      public void method1() {
      System.out.println("Rain 1");
      }
      public void method2() {
      System.out.println("Rain 2");
      }
      }

      public class Sleet extends Snow {
      public void method2() {
      System.out.println("Sleet 2");
      super.method2();
      method3();
      }
      public void method3() {
      System.out.println("Sleet 3");
      }
      }

      public class Fog extends Sleet {
      public void method1() {
      System.out.println("Fog 1");
      }
      public void method3() {
      System.out.println("Fog 3");
      }
      }

      public class Test{
      public static void main(String[] args) {
      Snow var1 = new Sleet();
      var1.method2();
      // static type Snow: method2, method3 can be used
      // dynamic type Sleet: method2, method3 are overridden
      // Result: Sleet 2 => Snow 2 => Sleet 3

      Snow var2 = new Rain();
      var2.method1();
      // static type Snow: method2, method3 can be used
      // dynamic type Rain: method2 is overridden
      // Result: Error, method1 only exists in Rain class, it's not in the Snow class

      Snow var3 = new Rain();
      ((Sleet) var3).method2();
      // Error: a Rain is not a Sleet, there is no inheritance relationship, so you cannot conduct the cast

      Fog var4 = new Fog();
      var4.method2();
      // Fog overrides method1 and method3, it inherits method2 from Sleet
      // System.out.println("Sleet 2"); => Sleet 2
      // super.method2(); => Snow 2, because super is the super class of where it is called
      // method3(); => Fog 3, because there is an overridden version of method 3 in Fog class
      //Result: Sleet 2 => Snow 2 => Fog 3

      }
      }
  2. Abstract Class
    • An abstract class is a placeholder in a class hierarchy that represents a generic concept
    • An abstract class cannot be instantiated
    • Syntax: public abstract class Name{}
    • An abstract class can contain all abstract methods, or it can contain all concrete methods, or it can contain both concrete and abstract methods
    • Abstract method: an abstract method is a method that has just the signature but does not contain implemenetation
      • Abstract methods cannot be defined as final, because it must be overridden
    • Abstract class can have constructors
      • The constructor of an abstract class should be protected
      • The constructor in subclasses can invoke constructors abstract classes

Lecture 14 2021/10/25

  1. Interface
    • Inheritance

      • Java supports single inheritance, meaning that a derived class can have only one parent class. For multiple inheritance, there may be conflicts
      • A Java class can extend another class and can implement multiple interfaces, a Java interface can extend multiple interfaces
    • An interface can have methods and fields just like the class, but methods declared in interface are by default abstract

    • Inheritance gives you an is-a relationship and code-sharing, interfaces give you an is-a relationship without code sharing

    • Syntax Example:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public interface Shape {
      public double area();
      public double perimeter();
      }

      public class Square implements Shape {
      private double side;

      public double area() {
      return this.side * this.side;
      }

      public double perimeter() {
      return 4 * side;
      }
      }

    • Interface are used for full abstraction, interface enables you to use polymorphism

    • Fields of interface

      • Interface can store fields, but they must be public, static and final
      • public: these fields will be accessed by the methods of the interface, these methods are implemented in subclasses of interface
      • static: interface cannot be instantiated, you cannot have an interface object to access these fields
      • final: ensures a field is assigned a constant value, methods are abstract and there is no other way to re-assign its value
    • Interface does not contain any constructors

    • Abstract Class v.s. Interface

      Abstract Class Interface
      Methods can be abstract and concrete Before Java 8, all methods should be abstrct. There can be default and static methods since Java 8
      Doesn't support multiple inheritance Supports multiple inheritance
      Can have final, non-final, static and non-static variables Variables should be public static final
      Can implement an interface Cannot implement an abstract class
      Use abstract keyword to declare an abstract class Use interface keyword to declare an interface
      An abstract class can extend another class(can be a concrete class, for example, java.lang.Object) and implement multiple interfaces An interface can extend multiple interfaces
      Use extends to extend an abstract class Use implements to implement an interface
      Can have private, protected members Members are public by default
      Abstract classes can have constructors Interfaces cannot have constructors
  2. ArrayList Intro
    • Syntax: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    • Something from source code
      • Data array: transient Object[] elementData;
      • Size: private int size;
      • Initial size: private static final int DEFAULT_CAPACITY = 10;
      • Maximum size: public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
      • Something related to size grow:
        1
        2
        3
        4
        return grow(minCapacity: size + 1);
        int newCapacity = ArraysSupport.newLength(oldCapacity, minGrowth: minCapacity - oldCapacity, prefGrowth: oldCapacity >> 1)
        int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
        // This means that if conditions are met, newLength = oldLength + Math.max(1, oldLength >> 1)
      • Something related to size shrink
        1
        2
        3
        4
        5
        6
        7
        8
        public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
        elementData = (size == 0)
        ? EMPTY_ELEMENTDATA
        : Arrays.copyOf(elementData, size);
        }
        }
    • Usage: import java.util.ArrayList;
    • ArrayList<E> is a generic class
  3. Generic Class
    • Java Generics
      • Used to make an object usable for any types, while still preserving the type checking that Java allows
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // A concrete class
      public class PointBox {
      private Point p;

      public void put(Point p) {
      this.p = p;
      }

      public Point get() {
      return this.p;
      }
      }
      // A generic class
      public class Box<T> {
      private T obj;

      public void put(T obj) {
      this.obj = obj;
      }

      public T get() {
      return this.obj;
      }
      }
    • Generic class was added to Java in Java 5
  4. ArrayList Continued
    • Syntax
      • Formal one: ArrayList<Type> list = new ArrayList<Type>();
      • Java 7 diamond operator syntax: ArrayList<Type> list = new ArrayList<>();

Lecture 15 2021/10/27

  1. ArrayList Continued
    • Methods

      Method Description
      public boolean add(E e) Appends the specified element to the end of this list, returns true
      public void add(int index, E e) Inserts* the specified element at the specified position in this list
      public boolean addAll(Collection<? extends E> c) Appends all of the elements in the specified collection to the end of this list
      public boolean addAll(int index, Collection<? extends E> c) Inserts all of the elements in the specified collection into this list, starting at the specified position
      public void clear() Removes all of the elements from this list
      public Object clone() Returns a shallow copy of this ArrayList instance
      public boolean contains(Object o) Returns true if this list contains the specified element
      public int indexOf(Object o) Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element
      public int lastIndexOf(Object o) Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element
      public E get(int index) Returns the element at the specified position in this list
      public E set(int index, E element) Replaces the element at the specified position in this list with the specified element, returns replaced value
      public E remove(int index) Removes the element at the specified position in this list
      public boolean remove(Object o) Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged
      public boolean removeAll(Collection<?> c) Removes from this list all of its elements that are contained in the specified collection
      public boolean retainAll(Collection<?> c) Retains only the elements in this list that are contained in the specified collection
      size() Returns the number of elements in this list
      public List<E> subList(int fromIndex, int toIndex) Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive
    • Dynamic Change

      • Add method
        1
        2
        3
        4
        5
        6
        7
        8
        9
        // Loop from the leftmost part
        for (int i = 0; i < list.size(); i += 2) {
        list.add(i, "-");
        }

        // Loop from the rightmost part
        for (int i = list.size() - 1; i > -1; i--) {
        list.add(i, "-");
        }
      • Remove method
        1
        2
        3
        4
        5
        6
        7
        8
        // Loop from the leftmost part
        for (int i = 0; i < list.size(); i++) {
        list.remove(i);
        }
        // Loop from the rightmost part
        for (int i = list.size() - 2; i > -1; i -= 2) {
        list.remove(i);
        }
  2. Runtime Efficiency
    • Empirical analysis
      • Run programs to test algorithms
      • Limitations:
        • Experiments can be done only on a limited set of test inputs
        • The experiments need to be held constant, which means the hardware environment and the software environment should be the same
      • Theoretical analysis
        • Consider all possible inputs, perform high-level description, independent of environments

        • Algorithm growth rates:

          • Big-Oh: it's a measure of the longest amount of time it could possibly take for the algorithm to complete

          • Complexity classes

            Class Big-Oh
            constant \(O(1)\)
            logarithmic \(O(log_2 n)\)
            linear \(O(n)\)
            log-linear \(O(nlog_2 n)\)
            quadratic \(O(n^2)\)
            qubic \(O(n^3)\)
            exponential \(O(2^n)\)
        • ArrayList efficiency

          Method Complexity
          add \(O(1)\)
          add(index, value) \(O(n)\)
          indexOf \(O(n)\)
          get \(O(1)\)
          remove \(O(n)\)
          set \(O(1)\)
          size \(O(1)\)
  3. Wrapper Class
    • Wrapper class

      Primitive Type Wrapper Type
      byte Byte
      boolean Boolean
      short Short
      character Character
      int Integer
      long Long
      float Float
      double Double
    • There is auto-boxing and auto-unboxing in Java

Lecture 16 2021/11/01

  1. The Comparable Interface
    • Natural ordering
      • Many types have the notation of natural ordering that describes whether one value of that type is "less than" or "greater than" another
      • Not all types have a natural ordering
    • The interface
      • It's inside the java.lang package
        1
        2
        3
        public interface Comparable<T> {
        public int compareTo(T o);
        }
      • Situations
        • If \(this < that\), then this.compareTo(that) < 0
        • If \(this == that\), then this.compareTo(that) = 0
        • If \(this > that\), then this.compareTo(that) > 0
      • Implementation
        • Syntax public class A implements Comparable<A>

Lecture 17 2021/11/03

  1. ArrayList
    • Summary
      • It is internally stored in an array, so it has a certain capacity
      • It is always at least as large as the list size
      • As elements are added to an ArrayList, its capacity grows "automatically"
      • Random access to elements: add(i)/get(i) is \(O(1)\), add(list.length - 1) is also \(O(1)\)
      • Remove add add in the middle are \(O(n)\)
  2. LinkedList
    • Collection
      • It is an object that stores data inside it
      • Collection example:
        • List: collections of elements
        • Set: a collections of elements that is guaranteed to contain no duplicated
        • Map: a collection of (key, value) pairs in which each key is associated with a corresponding value
        • Stack: a collection with LIFO
        • Queue: a collection with FIFO
      • Collection<E> is an interface
      • The collection framework
    • List
      • It is an ordered sequence of elements, one of the most basic collections
      • Maintain elements in the order they were added
      • Duplicates are allowed
      • Some operations are efficient

Lecture 18 2021/11/08

  1. LinkedList
    • Introduction
      • A linked list is a list implemented using a liked sequence of values
        • Each value is stored in a node, which also contains references to its neighbor nodes
        • The list keeps a reference to the first and/or last node
        • In Java, represented by the class LinkedList
      • Node class
        • Example
          1
          2
          3
          4
          public class ListNode {
          Integer data;
          ListNode next;
          }
    • The list interface
      • import java.util.List;
      • public interface List<E> extends Collections<E>;
      • Methods
        • public void add(int index, E elements)
        • public E get(int index)
        • public int indexOf(Object o)
        • public int lastIndexOf(Object o)
        • public E remove(int index)
        • public Object set(int index, E element)
    • The LinkedList in Java implements a double linked list
    • The get/add method is slow, you should use an iterator instead, you should not modify the list after an iterator is created, otherwise a ConcurrentModificationException will be caused
    • The Iterator<E> interface
      • import java.util.Iterator;
      • Methods:
        • public boolean hasNext()
        • public E next(): returns the current item, move the cursor forward
        • public void remove(): removes the last item returned by next method
      • Example
        1
        2
        3
        4
        5
        6
        LinkedList<String> list = new LinkedList<>();
        Iterator iter = list.iterator();
        while(iter.hasNext()) {
        String item = iter.next();
        System.out.println(item);
        }
      • Use Sieve of Eratosthenes to find prime numbers
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        public static List<Integer> primes(int n)  {
        List<Integer> nums = new LinkedList<>();
        List<Integer> primes = new LinkedList<>();
        for (int i = 2; i <= n; i++) {
        nums.add(i);
        }
        while (!nums.isEmpty()) {
        int p = nums.remove(0);
        primes.add(p);
        Iterator<Integer> iter = nums.iterator();
        while (iter.hasNext()) {
        int num = iter.next();
        if (num % p == 0 ) {
        iter.remove();
        }
        }
        }
        return primes;
        }
    • The LinkedList class implements the ListIterator class, it's more powerful than Iterator
      • import java.util.ListIterator
      • Example
        1
        2
        3
        4
        5
        LinkedList<String> list = new LinkedList<>();
        ListIterator iter = list.listIterator();
        while (iter.hasNext) {
        System.out.println(iter.next());
        }
    • Collections Class
      • import java.util.Collections;
      • Methods
        • binarySearch(list, value)
        • copy(dest, source)
        • fill(list, value)
        • max(list), min(list)
        • replaceAll(list, oldValue, newValue)
        • reverse(list)
        • rotate(list, distance)
        • sort(list)
        • swap(list, index1, index2)
    • Abstract Data Types(ADTS)
      • ADT is a general specification of a data structure
        • It specifies what data the data structure can hold
        • It specifies what operations can be performed on the data
        • It does not how the data structure hold the data internally, nor how it implements each operation
      • ArrayList and LinkedList both implement the data/operations specified by the list ADT
        • In Java, ArrayList and LinkedList both implement List interface

        • You can use polymorphism with ADT

          1
          List<String> list = new LinkedList<>();

        • Comparison of ArrayList and LinkedList

          ArrayList LinkedList
          Uses a dynamic array Uses a doubly linked list
          Manipulation is slow, because internal shifting is required with some operations Manipulation is faster, no shifting is required
          It can act as a list It can act as a list and queue
          Better for storing and accessing data Better for manipulating data

Lecture 19 2021/11/10

  1. Recursion
    • Why recursion
      • Can solve some kinds of problems better than iteration
      • Leads to elegant, simplistic, short code when used well
      • Many programming languages use recursion exclusively(no loops), such as Scheme, ML and Haskell
    • Programming techniques
      • Divide and conquer: recursion
      • Dynamic programming
      • Greedy
    • When use recursion
      • The problem can be broken into smaller parts
      • Each part is a smaller version of the original problem
      • There is a base case that can be solved immediately
    • Rules of recursion
      • A correct implementations of a recursive algorithms has at least two cases:
        • Base case: a simple occurrence that can be answered directly
        • Recursive case: a more complex occurrence of the problem that can be described in terms of smaller occurrences of the same problem

Lecture 20 2021/11/15

  1. Recursion
    • Example one: factorial of n
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public static int factorialRecursion(int n) {
      if (n == 0) {
      return 1;
      }
      return n * factorialRecursion(n - 1);
      }

      public static int factorialIteration(int n) {
      if (n == 0) {
      return 1;
      }
      int product = 1;
      int i = 1;
      while (i <= n) {
      product *= i;
      i += 1;
      }
      return product;
      }
    • Run-time stack and activation frames
      • Java maintains a run-time stack on which it saves new information in the form of an activation frame
      • The activation frame contains storage of method arguments, local variables, the return address of the instruction that called the method
      • Whenever a new method is called, Java pushes a new activation frame onto the run-time stack
    • Example two: fibonacci number
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      public static int fibonacciRecursion(int n) {
      if (n == 0) {
      return 1;
      }
      if (n == 1) {
      return 1;
      }
      return fibonacciRecursion(n - 1) + fibonacciRecursion(n - 2);
      }

      public static int fibonacciIteration(int n) {
      if (n == 1 || n == 0) {
      return 1;
      }
      int a = 1;
      int b = 1;
      int c = 1;
      while (b <= n) {
      c = a + b;
      a = b;
      b = c;
      }
      return b;
      }
    • Efficiency of recursion
      • Recursive methods often have slow execution times relative to their iterative counterparts
      • The overhead of loop repetition is smaller than a method call and return
    • Tail recursion
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      public static int fibonacciTailRecursion(int fibCur, int fibPrev, int n) {
      if (n == 1) {
      return fibCur;
      }
      return fibonacciTailRecursion(fibCur + fibPrev, fibCur, n - 1);
      }

      public static int fibonacciWrapper(int n) {
      return fibonacciTailRecursion(1, 0, n);
      }

Lecture 21 2021/11/17

  1. Exercise
    • isPalindrome
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      // iterative method
      public static boolean isPalindromeIteration(String s) {
      for (int i = 0; i < s.length() / 2; i ++) {
      if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
      return false;
      }
      }
      return true;
      }
      // recursive method
      public static boolean isPalindromeRecursion(String s) {
      if (s.length() <= 1) {
      return true;
      }
      return s.charAt(0) == s.charAt(s.length() - 1) && isPalindromeRecursion(s.substring(1, s.length() - 1));
      }
    • binary search
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      private static int binarySearch(Object[] items, Object target, int lo, int hi) {
      if (lo > hi) {
      return -1;
      }
      int mid = (lo + hi) / 2;
      if (target.compareTo(items[mid]) == 0) {
      return mid;
      } else if (target.compareTo(items[mid]) < 0) {
      return binarySearch(items, target, lo, mid - 1);
      } else {
      return binarySearch(items, target, mid + 1, hi);
      }
      }

      public static int binarySearch(Object[] items, Object target) {
      return binarySearch(items, target, 0, items.length - 1);
      }
  2. Recursive Backtracking
    • Backtracking: a general algorithm for finding solutions to a computational problem by trying partial solutions and then abandoning them if they are not suitable.
    • Applications:
      • Producing all permutations of a set of values
      • Parsing languages
      • Games: anagrams, crosswords, word jumbles, 8 queens
      • Combinatorics and logic programming

Lecture 22 2021/11/22

  1. Set
    • Introduction

      • A set is a collection of unique values that can perform some operations
      • Java has an interface Set<E> to represent this kind of collection, it has exactly the methods of the Collection interface
      • There are two set implementation in Java: TreeSet and HashSet
        • TreeSet is based on TreeMap, and TreeMap is based on Red-Black tree
        • HashSet is based on HashMap
        • private static final Object PRESENT = new Object() in both HashSet and TreeSet
        • Null is allowed in HashSet but not in TreeSet
        • TreeSet ensures \(log(n)\) operations, items need implement Comparable with their natural order, or you need to give them an order using Comparator
      • Example
        1
        2
        3
        4
        5
        6
        import java.util.Set;
        import java.util.HashSet;
        import java.util.TreeSet;

        Set<String> s1 = new HashSet<>();
        Set<String> s2 = new TreeSet<>();
    • Set methods:

      • add(value)
      • contains(value)
      • remove(value)
      • clear()
      • size()
      • isEmpty()
      • toString()
    • Typical set operations

      • Subset: s1.containsAll(s2), returns true if \(s2 \subseteq s1\)
      • Union: s1.addAll(s2), \(s1\) becomes \(s1 \cup s2\), addAll() is a boolean method, if s1 is changed, returns true, otherwise returns false
      • Intersection: s1.retainAll(s2), \(s1\) becomes \(s1 \cap s2\), retainAll() is a boolean method, if s1 is changed, returns true, otherwise returns false
      • Difference: s1.removeAll(s2), \(s1\) becomes \(s1 - s2\), removeAll() is a boolean method, if s1 is changed, returns true, otherwise returns false
    • Comparison between HashSet and TreeSet

      HashSet TreeSet
      Can store data of any type Data should have natural ordering(implements the Comparable interface, overwrites compareTo method), or you should pass a Comparator(overwrites compare method)
      Can contain null elements Cannot contain null elements
      Based on HashMap with a private static final Object as value Based on TreeMap with a private static final Object as value
      add, remove, contains, size are constant operations add, remove, contains are \(O(log(N))\) operations
      Iterator is fail-fast: if the set is modified after the creation of the iterator, except the iterator's own remove method is called, a ConcurrentModificationException is thrown Iterator is fail-fast: if the set is modified after the creation of the iterator, except the iterator's own remove method is called, a ConcurrentModificationException is thrown

Lecture 23 2021/11/29

  1. The Map ADT
    • Map: holds a set of unique keys and a collection of values, where each key is associated with one value
    • Basic map operations:
      • put(key, value): adds/replaces a key-value pair
      • get(key): get the value associated with the key
      • remove(key): removes key-value pair
    • Collection View:
      • Map interface does not extends Collection interface, it does not have a iterator method
      • The keySet() and values() methods return a set of keys and a collection of values respectively, each is a collection exists conceptually within the map, the entrySet() method returns a set of entries within the map, each entry is an instance of java.util.Map.Entry interface
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);

        for (String key: map.keySet()) {
        System.out.println(key + " " + map.get(key));
        }

        for (Map.Entry<String, Integer> item: map.entrySet()) {
        System.out.println(item.getKey() + " " + item.getValue());
        }
        }
  2. Java Implementation
    • java.util.Map interface has two concrete subclasses, java.util.HashMap and java.util.TreeMap

    • Map methods:

      • clear()
      • containsKey(key), containsValue(value)
      • get(key), put(key, value), putAll(map), remove(key)
      • isEmpty(), size()
      • keySet(), values(), entrySet()
      • Map.Entry<K, V> interface:
        • getKey(), getValue()
    • Comparison between HashMap and TreeMap

      HashMap TreeMap
      Can store data of any type Data should have natural ordering or a Comparator should be provided
      Faster operations, based on HashTable Slower operations, based on Red-Black Tree
      Can contain 1 null key and multiple null values Cannot contain null key and can contain multiple null values
      get, put, size are \(O(1)\) get, put, size, containsKey are \(O(log(N))\)
      Iterator is fail-fast Iterator is fail-fast

Lecture 24 2021/12/01

  1. Stack
    • Stack: a collection based on the principle of adding elements and retrieving them in the opposite order
    • LIFO (Last in, first out)
    • Basic stack operations: push(item), pop(), peek()
    • java.util.Stack
    • You should use Deque when you want LIFO stack operations
      1
      Deque<Integer> stack = new ArrayDeque<>();
  2. Queue
    • FIFO