Essential Java APIs: String Handling, Collections, Dates, and Generics

Core API Concepts

Object & String Fundamentals

By default, the toString() method in the Object class returns the memory address (hash) of the object, which is often not useful. It is standrad practice to override this method to return a string representation of the object's internal state.

The == operator comapres primitive types by value, but for reference types, it compares memory addresses.

The String class is immutable; once created, its value cannot be changed. Reassigning a String variable points the reference to a new object in the string pool rather than modifying the original data.

// String comparison nuances
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2); // true (same pool reference)
System.out.println(s1 == s3); // false (different objects)
System.out.println(s1.equals(s3)); // true (content is same)

Essential String Methods

  • char[] toCharArray(): Converts the string into a character array for iteration.
  • String toLowerCase() / toUpperCase(): Case conversion.
  • boolean startsWith(String prefix) / endsWith(String suffix): Checks prefixes and suffixes.
  • boolean contains(CharSequence seq): Checks for substring existence.
  • String substring(int begin, int end): Extracts a portion of the string (inclusive start, exclusive end).

StringBuilder: Mutable Strings

StringBuilder acts as a mutable container for characters, improving performance when concatenating many strings.

StringBuilder builder = new StringBuilder("init");
builder.append("_data"); // Adds to the internal buffer
builder.delete(0, 4);   // Removes characters directly in the buffer
System.out.println(builder.toString()); // Output: _data

Capacity: If the appended content exceeds the default capacity (usually 16), the internal array expands (typically to 2 * oldCapacity + 2).

StringBuilder vs StringBuffer

Date and Time API

Legacy Date

The Date class (old API) uses getTime() to fetch milliseconds since the Unix epoch (1970-01-01).

long start = new Date().getTime();
// Simulate work
long end = new Date().getTime();
System.out.println("Elapsed: " + (end - start) + "ms");

Modern Date API (java.time)

LocalDate handles dates without time zones. LocalDateTime includes time.

LocalDate today = LocalDate.now();
System.out.println(today.getYear()); // e.g., 2024

// Manipulating dates
LocalDate futureDate = today.plusYears(3);
boolean isLeap = futureDate.isLeapYear();

Formatting and Parsing

Convert between Strings and Date objects using DateTimeFormatter.

LocalDateTime current = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = current.format(formatter);
System.out.println(formatted);

// Parsing string back to date
LocalDate parsedDate = LocalDate.parse("2012-10-12");

Regular Expressions

Regex provides a powerful way to match string patterns.

// Validate phone number pattern
String phoneRegex = "1[3-9]\\d{9}"; 
System.out.println("13837808450".matches(phoneRegex)); // true

// Validate email pattern
String emailRegex = "\\w+@\\w+\\.\\w+";
System.out.println("test@example.com".matches(emailRegex)); // true

Quantifiers: X? (0 or 1), X* (0 or more), X+ (1 or more), X{n,m} (between n and m).

Splitting and Replacing

String data = "one   two  three";
String[] parts = data.split("\\s+"); // Split by one or more spaces

String result = "apple123banana".replaceAll("\\d+", "-"); // "apple-banana"

Auto-boxing and Caching

Java automatically converts primitives to wrappers (boxing) and vice versa (unboxing).

Integer num = 100; // Auto-boxing: Integer.valueOf(100)
int val = num;     // Auto-unboxing: num.intValue()

Caching: Integer objects for values between -128 and 127 are cached. Thus, == returns true for these ranges.

Random and Generators

Generate pseudo-random numbers using the Random class.

Random rand = new Random();
int randomNum = rand.nextInt(10); // 0 to 9

// Simple verification code generator
char[] alphabet = new char[26];
for (int i = 0; i < 26; i++) alphabet[i] = (char) ('a' + i);

StringBuilder code = new StringBuilder();
for (int i = 0; i < 4; i++) code.append(alphabet[rand.nextInt(26)]);
System.out.println(code);

Collection Framework

Introduction to Collections

Collections solve the limitation of fixed-size arrays, allowing dynamic storage of elements.

Iteration Methods

Collections are typically traversed using Iterators or Enhanced For loops.

Collection<String> items = new ArrayList<>();
items.add("A");
items.add("B");

// 1. Iterator
Iterator<String> it = items.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

// 2. Enhanced For
for (String item : items) {
    System.out.println(item);
}

Note: Do not modify a collection structurally (add/remove) while iterating using the collection's methods; use the iterator's remove method instead to avoid ConcurrentModificationException.

Generics

Generics enforce type safety at compile time, eliminating the need for casting.

// Generic Class
class Container<T> {
    private T value;
    public void set(T val) { this.value = val; }
    public T get() { return value; }
}

// Usage
Container<Integer> intBox = new Container<>();
intBox.set(10);
// intBox.set("text"); // Compile-time error

List Implementations

ArrayList (Fast Read, Slow Write)

Backed by a dynamic array. Default capacity is 10. When full, it grows by roughly 1.5x the old size.

ArrayList<Person> roster = new ArrayList<>();
roster.add(new Person("Alice", 30));

// Access by index
Person p = roster.get(0); 

LinkedList (Slow Read, Fast Write)

Backed by a doubly-linked list. Efficient for inserting/removing at the ends.

LinkedList<String> queue = new LinkedList<>();
queue.addFirst("First");
queue.addLast("Last");
System.out.println(queue.getFirst()); // First

Set Interface

Sets do not allow duplicates and have no specific order (unless using LinkedHashSet).

HashSet and Hashing

Uniqueness is determined by hashCode() and equals().

  1. If hash codes differ, the element is added.
  2. If hash codes are the same, equals() is checked.
  3. If equals() is true, the element is considered a duplicate and not added.
// Overriding equals and hashCode in a model class
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

LinkedHashSet

Similar to HashSet but maintains insersion order.

Map Interface

Maps store key-value pairs (e.g., ID to Name).

HashMap Operations

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "John");
map.put(2, "Jane");

String name = map.get(1); // Returns "John"
boolean exists = map.containsKey(2);

Map Traversal

Maps do not have a direct iterator, so they must be converted to a Set.

// 1. Key Set approach
for (Integer key : map.keySet()) {
    System.out.println(key + ": " + map.get(key));
}

// 2. Entry Set approach (more efficient)
for (Map.Entry<Integer, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

LinkedHashMap

Maintains the order of keys based on insertion.

Advanced Utilities

Nested Collections

Collections can hold other collections.

HashMap<String, HashMap<String, String>> school = new HashMap<>();
HashMap<String, String> classA = new HashMap<>();
classA.put("001", "Student A");

school.put("Class A", classA);

Varargs

Allows passing a variable number of arguments to a method.

public void printAll(String... messages) {
    for (String msg : messages) {
        System.out.println(msg);
    }
}
// Call: printAll("Hello", "World");

Arrays and Collections Tools

  • Arrays.asList(T... a): Converts an array to a fixed-size list.
  • Collections.addAll(Collection, T...): Adds elements to a collection.
  • Collections.shuffle(List): Randomizes the order of a list.

Wildcards

Used to restrict the types that can be used in generics.

  • ? extends T: Upper bound (T or subclasses).
  • ? super T: Lower bound (T or superclasses).

Tags: java string Collections Framework generics hashmap

Posted on Fri, 15 May 2026 17:35:22 +0000 by m00nz00mer