Code-Alongs

Code-Along 1: Sets Implementation

What You'll Learn

In this code-along, you'll implement a comprehensive Sets solution that demonstrates:

  • How to create and initialize different types of Sets (HashSet, LinkedHashSet, TreeSet)
  • How to add, remove, and check for the presence of elements in a Set
  • How to iterate over Set elements using enhanced for loops
  • How to perform set operations like union, intersection, and difference
  • How to use Sets to ensure uniqueness in a collection of objects

Key Concepts

// Creating different types of Sets
Set<String> hashSet = new HashSet<>();       // No guaranteed order, fastest performance
Set<String> linkedHashSet = new LinkedHashSet<>(); // Maintains insertion order
Set<String> treeSet = new TreeSet<>();       // Elements stored in natural order (sorted)

// Basic operations
hashSet.add("element");       // Add an element
boolean contained = hashSet.contains("element");  // Check if element exists
boolean removed = hashSet.remove("element");      // Remove an element
int size = hashSet.size();    // Get number of elements
boolean isEmpty = hashSet.isEmpty(); // Check if set is empty

// Set operations using built-in methods
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c"));
Set<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d"));

// Union: set1 ∪ set2 = {a, b, c, d}
Set<String> union = new HashSet<>(set1);
union.addAll(set2);

// Intersection: set1 ∩ set2 = {b, c}
Set<String> intersection = new HashSet<>(set1);
intersection.retainAll(set2);

// Difference: set1 - set2 = {a}
Set<String> difference = new HashSet<>(set1);
difference.removeAll(set2);

Code-Along 2: Maps Implementation

What You'll Learn

In this code-along, you'll implement a Maps solution that demonstrates:

  • How to create and initialize different types of Maps (HashMap, LinkedHashMap, TreeMap)
  • How to add, retrieve, update, and remove key-value pairs
  • How to iterate over a Map's entries, keys, and values
  • How to use Maps for efficient data lookups and relationships
  • How to handle custom objects as keys with proper hashCode and equals implementation

Key Concepts

// Creating different types of Maps
Map<String, Integer> hashMap = new HashMap<>();          // No guaranteed order, fastest performance
Map<String, Integer> linkedHashMap = new LinkedHashMap<>(); // Maintains insertion order
Map<String, Integer> treeMap = new TreeMap<>();           // Keys stored in natural order (sorted)

// Basic operations
hashMap.put("key1", 100);              // Add/update a key-value pair
Integer value = hashMap.get("key1");   // Retrieve a value by key
boolean hasKey = hashMap.containsKey("key1");  // Check if key exists
boolean hasValue = hashMap.containsValue(100); // Check if value exists
Integer removed = hashMap.remove("key1");      // Remove entry by key
int size = hashMap.size();             // Get number of entries

// Handling missing keys
Integer valueOrDefault = hashMap.getOrDefault("missing", 0); // Returns 0 if key not found

// Iteration methods
// 1. Using entrySet() - most efficient
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
    String key = entry.getKey();
    Integer val = entry.getValue();
    System.out.println(key + " -> " + val);
}

// 2. Using keySet() - when you need the key to look up values
for (String key : hashMap.keySet()) {
    Integer val = hashMap.get(key);
    System.out.println(key + " -> " + val);
}

// 3. Using values() - when you only care about values
for (Integer val : hashMap.values()) {
    System.out.println("Value: " + val);
}

Code-Along 3: Exception Handling Techniques

What You'll Learn

In this code-along, you'll implement exception handling techniques that demonstrate:

  • How to use try-catch blocks to handle exceptions
  • How to create and use custom exceptions
  • When to use checked vs. unchecked exceptions
  • Proper exception propagation patterns
  • How to use finally blocks and try-with-resources

Key Concepts

// Basic try-catch structure
try {
    // Code that might throw an exception
    riskyOperation();
} catch (SpecificException e) {
    // Handle the specific exception
    System.out.println("Specific exception: " + e.getMessage());
} catch (Exception e) {
    // Catch-all for other exceptions (use sparingly)
    System.out.println("Unexpected error: " + e.getMessage());
} finally {
    // Code that always executes, whether exception occurs or not
    cleanup();
}

// Try-with-resources (auto-closes resources)
try (
    FileInputStream fis = new FileInputStream("file.txt");
    BufferedReader reader = new BufferedReader(new InputStreamReader(fis))
) {
    String line = reader.readLine();
    // Process the file...
} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
}

// Creating and throwing custom exceptions
public class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

// Method that throws a custom exception
public void validate(String input) throws CustomException {
    if (input == null || input.isEmpty()) {
        throw new CustomException("Input cannot be null or empty");
    }
    // Continue processing...
}