Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Core Development Guide: Exception Handling, Collections Framework, Map and Stream API Usage

Tech 1

Exception Handling

Exception Hierarchy

Java exceptions are divided into two main categories: runtime exceptions (unchecked exceptions) and compile-time exceptions (checked exceptions), all inheriting from the Throwable class.

throws Keyword

The throws keyword is used at method declaration to indicate that the method may throw specified exceptions, leaving the exception handling responsibility to the method caller.

Custom Exceptions

You can implement custom exceptions by inheriting from existing exception classes. If you inherit from RuntimeException, the custom exception is an unchecked exception; if you inherit from Exception, it is a checked exception that requires explicit throws declaration on methods that throw it.

// Custom unchecked exception for invalid age input
public class InvalidAgeException extends RuntimeException {
    public InvalidAgeException() {}

    public InvalidAgeException(String errorMessage) {
        super(errorMessage);
    }
}

public class CustomExceptionDemo {
    public static void main(String[] args) {
        try {
            validateUserAge();
        } catch (InvalidAgeException e) {
            String errorMsg = e.getMessage();
            System.out.println("Error occurred: " + errorMsg);
        }
    }

    // throw keyword is used inside method to throw a concrete exception object
    public static void validateUserAge() {
        Scanner ageScanner = new Scanner(System.in);
        System.out.println("Please enter student age:");
        int inputAge = ageScanner.nextInt();
        if (inputAge < 0 || inputAge > 150) {
            throw new InvalidAgeException("Input age is out of valid range (0~150)");
        }
        System.out.println("Valid age entered: " + inputAge);
    }
}

Note: If your custom exception inherits from a checked exception class, all methods throwing this exception must declare it with the throws keyword.

Difference between throws and throw

throws throw
Used after method signature Used inside method body
Declares types of exceptions the method may throw Throws a concrete exception instance
Can declare multiple exception types Can only throw one exception object at a time
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class ThrowsUsageDemo {
    public static void main(String[] args) {
        try {
            parseDateAndInputNumber();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public static void parseDateAndInputNumber() throws NumberFormatException, ParseException {
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
        Date parsedDate = dateFormatter.parse("2022-4-13");
        readAndParseInteger();
    }

    public static void readAndParseInteger() throws NumberFormatException {
        Scanner inputScanner = new Scanner(System.in);
        System.out.println("Please enter a number:");
        String inputStr = inputScanner.next();
        int parsedNum = Integer.parseInt(inputStr);
        System.out.println("Parsed number: " + parsedNum);
    }
}

Collections Framework

Core Collection Types and Characteristics

  • List series: Ordered, allows duplicate elements, supports index access
  • Set series: Unordered (most implementations), does not allow duplicate elements, no index support
import java.util.ArrayList;
import java.util.HashSet;

public class CollectionTypeComparisonDemo {
    public static void main(String[] args) {
        // List implementation: ordered, allows duplicates, index supported
        ArrayList<String> orderedFruitList = new ArrayList<>();
        orderedFruitList.add("Banana");
        orderedFruitList.add("Apple");
        orderedFruitList.add("Cherry");
        orderedFruitList.add("Date");

        for (int i = 0; i < orderedFruitList.size(); i++) {
            String fruit = orderedFruitList.get(i);
            System.out.println(fruit);
        }

        System.out.println("--------------------------");

        // Set implementation: unordered, no duplicates, no index support
        HashSet<String> uniqueFruitSet = new HashSet<>();
        uniqueFruitSet.add("Banana");
        uniqueFruitSet.add("Apple");
        uniqueFruitSet.add("Cherry");
        uniqueFruitSet.add("Apple"); // duplicate element will be ignored

        // Set has no get() method for index access
        System.out.println(uniqueFruitSet); // Output: [Apple, Banana, Cherry] (order may vary)
    }
}

Common Methods of Collection Interface

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class CommonCollectionApiDemo {
    public static void main(String[] args) {
        Collection<String> celebrityCollection = new ArrayList<>();

        // Add elements
        celebrityCollection.add("Liu Yifei");
        celebrityCollection.add("Gigi Lai");
        celebrityCollection.add("Athena Chu");
        System.out.println("Initial collection: " + celebrityCollection);

        // Remove specified element
        boolean isRemoved = celebrityCollection.remove("Liu Yifei");
        System.out.println("Is Liu Yifei removed: " + isRemoved);
        System.out.println("After removal: " + celebrityCollection);

        // Check if element exists
        boolean hasOldWang = celebrityCollection.contains("Old Wang");
        System.out.println("Contains Old Wang: " + hasOldWang);

        // Check if collection is empty
        boolean isEmpty = celebrityCollection.isEmpty();
        System.out.println("Is collection empty: " + isEmpty);

        // Convert collection to array
        String[] celebrityArr = new String[celebrityCollection.size()];
        celebrityCollection.toArray(celebrityArr);
        System.out.println("Converted array: " + Arrays.toString(celebrityArr));

        // Add all elements from another collection
        Collection<String> newCelebrityCollection = new ArrayList<>();
        newCelebrityCollection.add("Tian Liang");
        newCelebrityCollection.add("Li Xiao");
        celebrityCollection.addAll(newCelebrityCollection);
        System.out.println("After adding all elements: " + celebrityCollection);

        // Clear all elements
        celebrityCollection.clear();
        System.out.println("After clear: " + celebrityCollection);
    }
}

Collection Traversal Methods

1. Iterator Traversal

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class IteratorTraversalDemo {
    public static void main(String[] args) {
        Collection<String> celebrityCollection = new ArrayList<>();
        celebrityCollection.add("Liu Yifei");
        celebrityCollection.add("Gigi Lai");
        celebrityCollection.add("Athena Chu");

        // Get iterator instance for the collection
        Iterator<String> collectionIterator = celebrityCollection.iterator();
        // Traverse while there are remaining elements
        while (collectionIterator.hasNext()) {
            String currentElement = collectionIterator.next();
            System.out.println(currentElement);
        }
    }
}

2. Enhanced For Loop Traversal

import java.util.ArrayList;
import java.util.Collection;

public class EnhancedForLoopDemo {
    public static void main(String[] args) {
        Collection<String> celebrityCollection = new ArrayList<>();
        celebrityCollection.add("Liu Yifei");
        celebrityCollection.add("Gigi Lai");
        celebrityCollection.add("Athena Chu");

        for (String celebrity : celebrityCollection) {
            System.out.println(celebrity);
        }
    }
}

3. forEach Lambda Traversal

import java.util.ArrayList;
import java.util.Collection;

public class ForeachLambdaDemo {
    public static void main(String[] args) {
        Collection<String> celebrityCollection = new ArrayList<>();
        celebrityCollection.add("Liu Yifei");
        celebrityCollection.add("Gigi Lai");
        celebrityCollection.add("Athena Chu");

        // Anonymous inner class implementation
        celebrityCollection.forEach(System.out::println);

        // Simplified lambda implementation
        celebrityCollection.forEach(celebrity -> System.out.println(celebrity));
    }
}

Special Notes for Collection Operations

  • LinkedHashSet maintains insertion order when retrieving elements
  • If you need to remove elements during traversal, only use the remove() method of the iterator to avoid concurrent modification exceptions
  • Sort rule: In custom comparators, returning o1 - o2 results in ascending order, returning o2 - o1 results in descending order
import java.util.ArrayList;
import java.util.Iterator;

public class IteratorRemoveElementDemo {
    public static void main(String[] args) {
        ArrayList<String> celebrityList = new ArrayList<>();
        celebrityList.add("Cecilia Cheung");
        celebrityList.add("Gigi Lai");
        celebrityList.add("Liu Yifei");

        Iterator<String> iterator = celebrityList.iterator();
        while (iterator.hasNext()) {
            String current = iterator.next();
            System.out.println(current);
            if (current.equals("Gigi Lai")) {
                iterator.remove(); // Safe removal during traversal
            }
        }
        System.out.println("After removal: " + celebrityList);
    }
}

Collections Utility Class

The java.util.Collections class provides a set of static utility methods for operating on collections.

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

public class CollectionsUtilityDemo {
    public static void main(String[] args) {
        ArrayList<String> celebrityList = new ArrayList<>();

        // Add multiple elements in one call
        Collections.addAll(celebrityList, "Liu Yifei", "Gigi Lai", "Cecilia Cheung");
        System.out.println("Initial list: " + celebrityList);

        // Shuffle elements randomly
        Collections.shuffle(celebrityList);
        System.out.println("After shuffle: " + celebrityList);

        // Default ascending sort
        Collections.sort(celebrityList);
        System.out.println("After ascending sort: " + celebrityList);

        // Custom descending sort
        Collections.sort(celebrityList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        System.out.println("After descending sort: " + celebrityList);
    }
}

Map Collection

A Map stores key-value pairs, where key are unique and values can be duplicated.

Map Traversal Methods

1. Key Lookup Traversal

import java.util.HashMap;
import java.util.Set;

public class MapTraversalDemo {
    public static void main(String[] args) {
        HashMap<String, String> characterPairMap = new HashMap<>();
        characterPairMap.put("Yang Guo", "Little Dragon Maiden");
        characterPairMap.put("Guo Jing", "Huang Rong");
        characterPairMap.put("Nobita", "Shizuka");

        // Get all keys first, then lookup values by key
        Set<String> keySet = characterPairMap.keySet();
        for (String key : keySet) {
            String value = characterPairMap.get(key);
            System.out.println(key + " : " + value);
        }
    }
}

2. Key-Value Entry Traversal

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapEntryTraversalDemo {
    public static void main(String[] args) {
        HashMap<String, String> characterPairMap = new HashMap<>();
        characterPairMap.put("Yang Guo", "Little Dragon Maiden");
        characterPairMap.put("Guo Jing", "Huang Rong");
        characterPairMap.put("Nobita", "Shizuka");

        // Get all key-value entry objects
        Set<Map.Entry<String, String>> entrySet = characterPairMap.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " ---- " + value);
        }
    }
}

3. Lambda forEach Traversal

import java.util.HashMap;

public class MapLambdaTraversalDemo {
    public static void main(String[] args) {
        HashMap<String, String> characterPairMap = new HashMap<>();
        characterPairMap.put("Yang Guo", "Little Dragon Maiden");
        characterPairMap.put("Guo Jing", "Huang Rong");
        characterPairMap.put("Nobita", "Shizuka");

        // Simplified lambda traversal
        characterPairMap.forEach((key, value) -> System.out.println(key + " ---- " + value));
    }
}

Nested Map Usage Example

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class NestedMapDemo {
    public static void main(String[] args) {
        HashMap<String, List<String>> provinceCityMap = new HashMap<>();

        ArrayList<String> jiangsuCities = new ArrayList<>();
        Collections.addAll(jiangsuCities, "Nanjing", "Yangzhou");

        ArrayList<String> hubeiCities = new ArrayList<>();
        Collections.addAll(hubeiCities, "Wuhan", "Xiaogan");

        ArrayList<String> hebeiCities = new ArrayList<>();
        Collections.addAll(hebeiCities, "Shijiazhuang", "Tangshan");

        provinceCityMap.put("Jiangsu Province", jiangsuCities);
        provinceCityMap.put("Hubei Province", hubeiCities);
        provinceCityMap.put("Hebei Province", hebeiCities);

        Set<Map.Entry<String, List<String>>> entrySet = provinceCityMap.entrySet();
        for (Map.Entry<String, List<String>> entry : entrySet) {
            String province = entry.getKey();
            List<String> cities = entry.getValue();
            System.out.println(province + " : " + cities);
        }
    }
}

Stream API

Stream API provides a functional programming style for operating on collections and arrays efficiently.

Steps to Use Stream

  1. Get a Stream instance from a data source (collection, array, etc.)
  2. Perform entermediate operations (filter, map, sort, etc.)
  3. Perform terminal operations (collect, count, forEach, etc.) to get final result

Note: Double-column Map collections cannot get Stream directly, you need to convert them to single-column entry set first. Arrays can get Stream via Arrays.stream() or Stream.of().

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class StreamInitDemo {
    public static void main(String[] args) {
        // Get Stream from Map
        HashMap<String, String> characterPairMap = new HashMap<>();
        characterPairMap.put("Guo Jing", "Huang Rong");
        Stream<Map.Entry<String, String>> mapStream = characterPairMap.entrySet().stream();

        // Get Stream from array
        String[] celebrityArr = {"Zhang Wuji", "Zhou Zhiruo", "Zhao Min"};
        Stream<String> arrayStream1 = Arrays.stream(celebrityArr);
        Stream<String> arrayStream2 = Stream.of("Zhang Sanfeng", "Zhang Wuji");
    }
}

Common Stream Operations

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

public class StreamOperationDemo {
    public static void main(String[] args) {
        ArrayList<String> numberStrList = new ArrayList<>();
        Collections.addAll(numberStrList, "10", "7", "9", "11");

        // Convert string to integer, sort, then collect to new list
        List<Integer> sortedNumList = numberStrList.stream()
                .map(Integer::valueOf)
                .sorted()
                .collect(Collectors.toList());

        System.out.println(sortedNumList); // Output: [7, 9, 10, 11]
    }
}

Stream Notes

  1. Stream operations do not modify the original collection or array
  2. A Stream instance can only be used once, any operation after terminal operation will throw an expection

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.