Scribbling

[Java Basics] Major Difference to Python, C++, and JS 본문

Computer Science/Java

[Java Basics] Major Difference to Python, C++, and JS

focalpoint 2023. 1. 31. 04:58

 

This post will briefly summarize things I picked up about Java. I'll only handle stuff that is totally different from Python, C++, JavaScript context & syntax.

In Java, all classes are Reference Types. Except for primitive types, all the instances or objects are stored on Heap.

 

1. String

1.1. Methods

charAt(int): The charAt method accepts an index value as its input and returns the character located at that position.

substring(int, int): The substring method returns the characters between the specified start and end indices, exclusive of the end index.

substring(int): The substring method with a single integer argument returns the substring from that index to the end of the string.

  • indexOf: has two forms: one returns the index of the first occurrence of a given character and the other returns the index of the first occurrence of a given string.
  • lastIndexOf: similar to indexOf but returns the index of the last occurrence of a given character or string.
  • startsWith: returns true if the string starts with a specified prefix.
  • endsWith: returns true if the string ends with a specified suffix.
  • isEmpty: returns true if the string is empty.
  • equals: returns true if the string is equal to a specified string.
  • equalsIgnoreCase: returns true if the string is equal to a specified string, ignoring the case of its characters.

 

1.2. StringBuffer, StringBuilder

By default, String objects are immutable. For efficiency, consider StringBuffer and StringBuilder when modifying a String is needed. StringBuffer is thread-safe. Use StringBuilder on general purpose.

 

1.3. Methods ++

public class Main {

    public static void main(String[] args) {

        // check if there's non-blank in the string
        out.println("".isBlank());
        out.println("  ".isBlank());
        out.println(" a ".isBlank());

        // remove space
        out.println("   LR   ".strip());
        out.println("   LR   ".stripLeading());
        out.println("   LR   ".stripTrailing());

        // replacement
        out.println("   LR   ".replace(" ", "@"));

        // stream of lines
        "A\nB\nC\n".lines().forEach(out::println);

        // applying lambda function to the string
        String text = "abc,def,ccc";
        List<String> result = text.transform(t -> Arrays.asList(t.split(",")));
        System.out.println(result);

        // formatting
        out.println("My name is %s. Age is %d".formatted("Morgan", 25));




    }
}

 

2. Variable Arguments

public void func(int... values) {
    
    }

 

3. List

3.1. ArrayList, LinkedList, Vector

The difference between ArrayList and Vector is that Vector is thread-safe.

 

3.2. Sorting with Comparator

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

class DescStudentComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        if (o1.id < o2.id) {
            return -1;
        } else if (o1.id > o2.id) {
            return 1;
        } else {
            return o1.name.compareTo(o2.name);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");

        List<Student> students = List.of(
                new Student(3, "Morgan"),
                new Student(100, "Hoesu"),
                new Student(-3, "Bitch"),
                new Student(-3, "Apple"));

        students = new ArrayList<>(students);
        System.out.println(students);

        students.sort(new DescStudentComparator());
        System.out.println(students);



    }
}
        List<String> strs = new ArrayList<>(
                List.of("Ant", "Pants", "Beans2", "Gorilla", "K")
        );

        Collections.sort(strs);
        out.println(strs);

        // Anonymous Class 
        Comparator<String> comp = new Comparator<String>() {
            @Override
            public int compare(String str1, String str2) {
                return Integer.compare(str1.length(), str2.length());
            }
        };

        Collections.sort(strs, comp);
        out.println(strs);

 

3.3. Ummutable List

        List<String> names = new ArrayList<String>();
        names.add("Morgan");
        names.add("Chun");

        List<String> names2 = List.copyOf(names);
        out.println(names2);

 

4. Set

4.1. HashSet, LinkedHashSet, TreeSet

import java.util.*;


public class Main {
    public static void main(String[] args) {

        /*
        * HashSet corresponds to Set in Python
        */
        Set<Integer> nums1 = new HashSet<>();
        nums1.add(765432);
        nums1.add(765);
        nums1.add(123);
        System.out.println(nums1);

        /*
        * LinkedHashSet is a set
        * That keeps the data sorted along the input order
         */

        Set<Integer> nums2 = new LinkedHashSet<>();
        nums2.add(765432);
        nums2.add(765);
        nums2.add(123);
        System.out.println(nums2);

        /*
         * TreeSet is a set
         * That keeps the data sorted along their values
         */

        Set<Integer> num3 = new TreeSet<>();
        num3.add(765432);
        num3.add(765);
        num3.add(123);
        System.out.println(num3);

    }
}

 

4.2. TreeSet

import java.util.*;


public class Main {
    public static void main(String[] args) {

        TreeSet<Integer> nums = new TreeSet<Integer>(
                Set.of(65, 34, 54, 12, 99)
        );

        // outputs the value <= 65
        System.out.println(nums.floor(65));

        // outputs the value < 65
        System.out.println(nums.lower(65));

        System.out.println(nums.ceiling(65));
        System.out.println(nums.higher(65));

        // outputs the values 20 <= val < 65
        System.out.println(nums.subSet(20, 65));

        // outputs the values 20 <= val <= 65
        System.out.println(nums.subSet(20, true, 65, true));

        // outputs the values < 65
        System.out.println(nums.headSet(65));

        System.out.println(nums.tailSet(65));

    }
}

 

 

 

5. Queue

5.1. PriorityQueue

import java.util.*;




public class Main {
    public static void main(String[] args) {

        // Priority Queue stores data in natural order
        Queue<String> q = new PriorityQueue<String>();

        // Popping Element in the queue
        System.out.println(q.poll());

        // Adding Element
        q.offer("Apple");

        // Adding multiple Elements
        q.addAll(List.of("Zebra", "Monkey", "Cat"));

        System.out.println(q.poll());

        System.out.println(q);





    }
}

 

5.2. Custom Order in Priority Queue

import java.util.*;

class CustomComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return Integer.compare(o1.length(), o2.length());
    }
}


public class Main {
    public static void main(String[] args) {

        // Priority Queue stores data in natural order
        Queue<String> q = new PriorityQueue<String>(new CustomComparator());

        // Popping Element in the queue
        System.out.println(q.poll());

        // Adding Element
        q.offer("Apple");

        // Adding multiple Elements
        q.addAll(List.of("Zebra", "Monkey", "Cat"));

        System.out.println(q.poll());

        System.out.println(q);





    }
}

 

6. Map

6.1.

HashMap: Unsorted, Unordered, allows a key with null value

HashTable: Similar to HashMap, but thread-safe. Does not allow a key with null value

LinkedHashMap: Insertion Order is maintained

TreeMap: Sorted Order

 

6.2. Methods

        Map<String, Integer> map = new HashMap<String, Integer>(
                Map.of("A",3, "B", 5, "Z", 10)
        );

        System.out.println(map.get("Z"));

        System.out.println(map.containsKey("Z"));

        System.out.println(map.containsValue("Z"));

        System.out.println(map.keySet());

        System.out.println(map.values());

        map.put("F", 5);

 

6.3. Character/Word Occurrence Example

        String str = "This is an awesome question";

        Map<Character, Integer> map = new HashMap<>();

        char[] chars = str.toCharArray();

        for (char c : chars) {
            Integer val = map.get(c);
            if (val == null) {
                map.put(c, 1);
            } else {
                map.put(c, val+1);
            }
        }

        System.out.println(map);
        String str = "This is an awesome question";

        Map<String, Integer> map = new HashMap<>();

        String[] strs = str.split(" ");

        for (String s : strs) {
            Integer val = map.get(s);
            if (val == null) {
                map.put(s, 1);
            } else {
                map.put(s, val+1);
            }
        }

        System.out.println(map);

 

6.4. TreeMap Methods

        TreeMap<String, Integer> tm = new TreeMap<>();

        tm.put("F", 25);

        tm.put("Z", 5);

        tm.put("L", 250);

        tm.put("A", 15);

        // <-> lowerKey
        System.out.println(tm.higherKey("B"));

        // <-> floorKey
        System.out.println(tm.ceilingKey("B"));

        // <-> lastEntry
        System.out.println(tm.firstEntry());

        System.out.println(tm.subMap("B", "Z"));

        System.out.println(tm.subMap("B", true, "Z", false));

 

7. Functional Programming in Java

7.1. Stream

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

public class Main {
    public static void main(String[] args) {

        List<Integer> nums = new ArrayList<>(
                List.of(3, 5, 8, 213, 45, 4, 7)
        );

        System.out.println(nums.stream().reduce(0, (num1, num2) -> {  return num1 + num2; }));

        List<Integer> nums2 = nums.stream().distinct().sorted().map(e -> e*e).collect(Collectors.toList());

        System.out.println(nums2);

        List<String> strs = new ArrayList<>(
                List.of("Apple", "Ant", "Bat")
        );

        List<String> strs2 = strs.stream().map(s -> s.toLowerCase()).collect(Collectors.toList());

        System.out.println(strs2);

        




    }
}

 

7.2. Max, Min, Optional

Optional exists to prevent returning "null" values.

* Clients of an API might not know that you are returning back a null value.

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {

        List<Integer> nums = new ArrayList<>(
                List.of(3, 5, 8, 213, 45, 4, 7)
        );

        // max and min function returns "Optional Type"
        System.out.println(nums.stream().max((n1, n2) -> Integer.compare(n1, n2)));

        // use isPresent() to check whether there's a value
        System.out.println(nums.stream().max((n1, n2) -> Integer.compare(n1, n2)).isPresent());

        // use get() method to get the value
        System.out.println(nums.stream().max((n1, n2) -> Integer.compare(n1, n2)).get());

        List<Integer> nums2 = new ArrayList<>(
                List.of(2, 4, 6, 8)
        );

        System.out.println(nums.stream().filter(n -> n % 2 == 1).max((n1, n2) -> Integer.compare(n1, n2)).isPresent());

        // use orElse to set default value
        System.out.println(nums.stream().filter(n -> n % 2 == 1).max((n1, n2) -> Integer.compare(n1, n2)).orElse(0));

        System.out.println(nums.stream().filter(num -> num % 2 == 0).max((n1, n2) -> Integer.compare(n1, n2)).get());

        // IntStream returns "Integer Pipeline" use "boxed()" to convert it to Stream Object
        System.out.println(IntStream.range(1, 11).map(n -> n * n).boxed().collect(Collectors.toList()));
        


    }
}

 

7.3. Method Reference

Consider 'Method Reference' for better readability.

List<String> strs = new ArrayList<String>(
                List.of("Apple", "ShowMe", "TheMoney", "SanE", "MinHo")
        );

        // Example of Method Reference
        strs.stream().map(String::length).forEach(Main::print);

        // Below code can be replaced with
        System.out.println(List.of(23, 45, 67, 34).stream().filter(n -> n % 2 ==0).max((n1, n2) -> Integer.compare(n1, n2)).orElse(0));

        // This line
        System.out.println(List.of(23, 45, 67, 34).stream().filter(n -> n % 2 ==0).max(Integer::compare).orElse(0));

 

7.4. Predicate

        List<Integer> nums = List.of(34, 3, 4, 5, 677, 89, 88);

        Predicate<Integer> even = number -> number % 2 == 0;
        nums.stream().filter(even.negate()).forEach(out::print);
        out.println();
        nums.stream().filter(Main::isEven).forEach(out::print);
        out.println();
        nums.stream().filter(Predicate.not(Main::isEven)).forEach(out::print);
        out.println();

 

8. Multi-Threads, Concurrency

8.1.

class Task1 extends Thread {
    // Need to match the exact SIGNATURE below
    public void run() {
        System.out.println("Task1 is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task1 is Done");
    }
}

class Task2 implements Runnable {
    @Override
    public void run() {
        System.out.println("Task2 is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task2 is Done");
    }
}


public class Main {

    public static void main(String[] args) throws InterruptedException {

        Task1 t1 = new Task1();
        t1.start();

        Task2 t2 = new Task2();
        Thread thread2 = new Thread(t2);

        // Setting priority is just a request. Does not guarantee the order.
        thread2.setPriority(10);
        thread2.start();

        // wait for task1 & task2 to be completed
        t1.join();
        thread2.join();

        System.out.println("Task3 is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task3 is Done");
        



    }
}

 

8.2. Executor

class Task1 extends Thread {
    // Need to match the exact SIGNATURE below
    public void run() {
        System.out.println("Task1 is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task1 is Done");
    }
}

class Task2 implements Runnable {
    @Override
    public void run() {
        System.out.println("Task2 is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task2 is Done");
    }
}

class Task extends Thread {
    private int i;

    public Task(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println("Task " + i + " is Started");
        for (int i=0; i<1e8; i++){

        }
        System.out.println("Task " + i + " is Done");
}

public class Main {
    public static void main(String[] args) {

        // Executes one thread at a time
        ExecutorService exeService = Executors.newSingleThreadExecutor();
        exeService.execute(new Task1());
        exeService.execute(new Thread(new Task2()));
        System.out.println("Task3 is Started");
        for (int i=0; i<1e8; i++){
        }
        System.out.println("Task3 is Done");
        exeService.shutdown();

        // N threads at a time
        ExecutorService exeService2 = Executors.newFixedThreadPool(2);
        exeService2.execute(new Task(1));
        exeService2.execute(new Task(2));
        exeService2.execute(new Task(3));
        exeService2.execute(new Task(4));
        exeService2.execute(new Task(5));

        exeService2.shutdown();

    }
}

 

8.3. Thread returning objects

import java.util.concurrent.*;

// Thread returning objects
class Task implements Callable<String> {

    private final String name;

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

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return name + " ended";
    }


}


public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ExecutorService exeService = Executors.newFixedThreadPool(1);
        Future<String> ret = exeService.submit(new Task("first"));

        System.out.println("Here");

        // get() method will wait for the task to complete execution !
        System.out.println(ret.get());

        System.out.println("There");

        exeService.shutdown();

    }
}

 

- List of Threads

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

// Thread returning objects
class Task implements Callable<String> {

    private final String name;

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

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return name + " ended";
    }


}


public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        List<Task> tasks = List.of(new Task("first"), new Task("second"), new Task("third"));

        ExecutorService exeService = Executors.newFixedThreadPool(1);
        // invokeAny() method 
        List<Future<String>> ret = exeService.invokeAll(tasks);

        System.out.println("Here");

        // get() method will wait for the task to complete execution !
        for (Future<String> r: ret) {
            System.out.println(r.get());
        }

        System.out.println("There");

        exeService.shutdown();

    }
}

 

9. Enum

enum Season {
            WINTER(7), SPRING(1), SUMMER(2), FALL(3);

            private int val;
            private Season(int val) {
                this.val = val;
            }

            public int getVal() {
                return val;
            }

        }

        Season s1 = Season.FALL;
        out.println(s1);

        Season s2 = Season.valueOf("WINTER");
        out.println(s2);
        out.println(s2.ordinal());
        out.println(s2.getVal());

 

 

10. New Features

10.1. Local Variable Type Inference

public class Main {

    public static void main(String[] args) {

        // Local Variable Type Inference
        List<String> names1 = List.of("Morgan", "Chun");
        List<String> names2 = List.of("Hoesu", "Chu");
        var names3 = List.of("Blah", "Bla");
        var names = List.of(names1, names2, names3);
        names.stream().forEach(out::println);



    }
}

 

10.2. Switch Expression

    public static String dayOfWeek(int day) {
        String ret = switch (day) {
            case 0 -> "Sunday";
            case 1 -> "Monday";
            case 2 -> {
                System.out.println("Logic Block is also available");
                yield "Tuesday";
            }
            default -> throw new IllegalArgumentException("Invalid Day");
        };
        return ret;
    }

 

10.3. Text Blocks

        String str =
                """
                Line 1: %s
                  Line 2: %s
                Line 3
                Line 4
                       Line 5      
                Line 6""".formatted("Formatting", "Is also Possible");
        out.println(str);

 

10.4. Record

public class Main {
    record Person(String name, String email, String phoneNumber) {
        // public accessor methods, constructor, equals, hashcode, toString are autuomatically created
        // can custom implementations
        // compact construction is allowed
        public Person {
            if (name == null) {
                throw new IllegalArgumentException("Null Name");
            }
        }
    };

    public static void main(String[] args) {

        Person p1 = new Person("Morgan", "@gmail", "341");
        Person p2 = new Person("Hoesu", "gmail", "711");

        out.println(p1.name);
        out.println(p2.equals(p1));
        out.println(p2);


    }