Java Strings
Strings in Java are objects of the String class, and they are immutable, which means once a String is created, it cannot be changed. If you perform an operation that seems to modify a String, what’s actually happening is a new String object is being created with the modified content.
public class Main { public static void main(String[] args) { String str1 = “Hello, “; String str2 = “World!”; // String concatenation String str3 = str1 + str2; System.out.println(str3); // prints “Hello, World!” // Convert to uppercase String upper = str3.toUpperCase(); System.out.println(upper); // prints “HELLO, WORLD!” // Convert to lowercase String lower = str3.toLowerCase(); System.out.println(lower); // prints “hello, world!” // String length int length = str3.length(); System.out.println(length); // prints 13 // Substring String sub = str3.substring(0, 5);System.out.println(sub); // prints “Hello” // Index of a character or substring int index = str3.indexOf(“World”); System.out.println(index); // prints 7 // Replace characters in the string String replace = str3.replace(“World”, “Java”); System.out.println(replace); // prints “Hello, Java!” // Check if the string starts with a certain sequence boolean startsWith = str3.startsWith(“Hello”); System.out.println(startsWith); // prints true // Check if the string ends with a certain sequence boolean endsWith = str3.endsWith(“World!”); System.out.println(endsWith); // prints true // Trim (removes whitespace from both ends of the string) String str4 = ” Hello, World! “; System.out.println(str4.trim()); // prints “Hello, World!” } } |
StringBuffer and StringBuilder
StringBuffer and StringBuilder in Java are used for creating mutable (modifiable) strings. They are similar, but there is one important difference: StringBuffer is thread-safe (synchronized) while StringBuilder is not. This means you should use StringBuilder when working with single-threaded applications for better performance, and use StringBuffer when multiple threads are working on the same string. Below are some methods for StringBuffer and Stringbuilder.
Method | Description |
append(String s) | It is used to append the specified string with this string. The append() method is overloaded like append(char), append(boolean), append(int), append(float), append(double) etc. |
insert(int offset, String s) | It is used to insert the specified string with this string at the specified position. The insert() method is overloaded like insert(int, char), insert(int, boolean), insert(int, int), insert(int, float), insert(int, double) etc. |
replace(int startIndex, int endIndex, String str) | It is used to replace the string from specified startIndex and endIndex. |
delete(int startIndex, int endIndex) | It is used to delete the string from specified startIndex and endIndex. |
reverse() | is used to reverse the string. |
capacity() | It is used to return the current capacity. |
ensureCapacity(int minimumCapacity) | It is used to ensure the capacity at least equal to the given minimum. |
charAt(int index) | It is used to return the character at the specified position. |
length() | It is used to return the length of the string i.e. total number of characters. |
substring(int beginIndex) | It is used to return the substring from the specified beginIndex. |
substring(int beginIndex, int endIndex) | It is used to return the substring from the specified beginIndex and endIndex. |
toString() | Returns a string representing the data in this sequence. |
(* This table is from https://www.javatpoint.com/ )
Here’s an example of using StringBuilder:
public class Main { public static void main(String[] args) { StringBuilder sb = new StringBuilder(“Hello”); // Append to the string sb.append(“, World!”); System.out.println(sb); // prints “Hello, World!” // Insert into the string sb.insert(5, ” beautiful”); System.out.println(sb); // prints “Hello beautiful, World!” // Reverse the string sb.reverse(); System.out.println(sb); // prints “!dlroW ,lufituaeb olleH” // Delete from the string sb.delete(0, 2); System.out.println(sb); // prints “dlroW ,lufituaeb olleH” // Replace in the string sb.replace(5, 16, “brave”); System.out.println(sb); // prints “dlroW brave olleH” // Get substring String sub = sb.substring(6, 11); System.out.println(sub); // prints “brave” } } |
And here’s an example of using StringBuffer:
public class Main { public static void main(String[] args) { StringBuffer sb = new StringBuffer(“Hello”); // Append to the string sb.append(“, World!”); System.out.println(sb); // prints “Hello, World!” // Insert into the string sb.insert(5, ” beautiful”); System.out.println(sb); // prints “Hello beautiful, World!” // Reverse the string sb.reverse(); System.out.println(sb); // prints “!dlroW ,lufituaeb olleH” // Delete from the string sb.delete(0, 2); System.out.println(sb); // prints “dlroW ,lufituaeb olleH” // Replace in the string sb.replace(5, 16, “brave”); System.out.println(sb); // prints “dlroW brave olleH” // Get substring String sub = sb.substring(6, 11); System.out.println(sub); // prints “brave” } } |
In the examples above, you can see that the methods for StringBuilder and StringBuffer are the same. The output will also be the same. The difference comes in when you are working with multi-threaded applications.
Java Arrays
In Java, arrays are used to store multiple values in a single variable, of the same type. Arrays have various methods for manipulating their contents, most of them available in the Arrays utility class in the java.util package. To declare an array, define the variable type with square brackets:
Array.
Here’s an example showcasing different operations with arrays:
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] myArr = new int[5]; // Declaration, instantiation and initialize an array int[] arr = {5, 2, 8, 7, 1}; System.out.println(Arrays.toString(arr)); // prints [5, 2, 8, 7, 1] // Length of the array System.out.println(arr.length); // prints 5 // Access an array element System.out.println(arr[0]); // prints 5 // Modify an array element arr[0] = 10; System.out.println(Arrays.toString(arr)); // prints [10, 2, 8, 7, 1] // Sort the array Arrays.sort(arr); System.out.println(Arrays.toString(arr)); // prints [1, 2, 7, 8, 10] // Binary search in the array (the array should be sorted) int index = Arrays.binarySearch(arr, 7); System.out.println(index); // prints 2 // Compare two arrays int[] arr1 = {1, 2, 3}; int[] arr2 = {1, 2, 3}; boolean areEqual = Arrays.equals(arr1, arr2); System.out.println(areEqual); // prints true // Fill an array with a specific value Arrays.fill(arr, 5); System.out.println(Arrays.toString(arr)); // prints [5, 5, 5, 5, 5] // Copy an array int[] arrCopy = Arrays.copyOf(arr, arr.length); System.out.println(Arrays.toString(arrCopy)); // prints [5, 5, 5, 5, 5] } } |
Java ArrayList
ArrayList is part of Java’s collection framework. It’s a dynamic array, meaning its size can change dynamically and you can add and remove elements.
Here is an example code block showcasing various ArrayList methods:
import java.util.ArrayList; import java.util.Collections; public class Main { public static void main(String[] args) { // Creating an ArrayList ArrayList<String> list = new ArrayList<String>(); // Adding elements to the ArrayList list.add(“Apple”); list.add(“Banana”); list.add(“Cherry”); list.add(“Date”); list.add(“Elderberry”); System.out.println(“Original ArrayList: ” + list); // Accessing an element String fruit = list.get(0); System.out.println(“First fruit: ” + fruit); // Modifying an element list.set(0, “Apricot”); System.out.println(“ArrayList after modification: ” + list); // Removing an element list.remove(0); System.out.println(“ArrayList after removing first element: ” + list); // Checking if the ArrayList contains an element boolean containsBanana = list.contains(“Banana”); System.out.println(“Contains Banana? ” + containsBanana); // Sorting the ArrayList Collections.sort(list); System.out.println(“ArrayList after sorting: ” + list); // Finding the size of the ArrayList int size = list.size(); System.out.println(“Size of ArrayList: ” + size); // Clearing the ArrayList list.clear(); System.out.println(“ArrayList after clearing: ” + list); } } |
Java Linkedlist
The LinkedList class in Java is a part of the Java Collection Framework. It extends the AbstractList class and implements the List and Deque interfaces. Unlike ArrayList, LinkedList is a doubly-linked list, which means it can add or remove elements in constant time, but accessing elements takes longer.
Here’s an example of LinkedList and its methods:
import java.util.LinkedList; public class Main { public static void main(String[] args) { // Creating a LinkedList LinkedList<String> list = new LinkedList<String>(); // Adding elements to the LinkedList list.add(“Apple”); list.add(“Banana”); list.add(“Cherry”); System.out.println(“Original LinkedList: ” + list); // Adding an element at a specific position list.add(1, “Date”); System.out.println(“LinkedList after adding an element at index 1: ” + list); // Adding an element at the beginning list.addFirst(“Elderberry”); System.out.println(“LinkedList after adding an element at the beginning: ” + list); // Adding an element at the end list.addLast(“Fig”); System.out.println(“LinkedList after adding an element at the end: ” + list); // Accessing an element String fruit = list.get(0); System.out.println(“First fruit: ” + fruit); // Removing an element list.remove(0); System.out.println(“LinkedList after removing first element: ” + list); // Removing an element at the end list.removeLast(); System.out.println(“LinkedList after removing last element: ” + list); // Checking if the LinkedList contains an element boolean containsBanana = list.contains(“Banana”); System.out.println(“Contains Banana? ” + containsBanana); // Finding the size of the LinkedList int size = list.size(); System.out.println(“Size of LinkedList: ” + size); // Clearing the LinkedList list.clear(); System.out.println(“LinkedList after clearing: ” + list); } } |
Compare ArrayList vs. LinkedList
The LinkedList class is a collection which can contain many objects of the same type, just like the ArrayList. The LinkedList class has all of the same methods as the ArrayList class because they both implement the List interface. This means that you can add items, change items, remove items and clear the list in the same way. However, while the ArrayList class and the LinkedList class can be used in the same way, they are built very differently.
How the ArrayList works
The ArrayList class has a regular array inside it. When an element is added, it is placed into the array. If the array is not big enough, a new, larger array is created to replace the old one and the old one is removed.
How the LinkedList works
The LinkedList stores its items in “containers.” The list has a link to the first container and each container has a link to the next container in the list. To add an element to the list, the element is placed into a new container and that container is linked to one of the other containers in the list.
Use an ArrayList for storing and accessing data, and LinkedList to manipulate data.
Java HashMap
HashMap in Java is a part of the Java Collections Framework. It is used to store key & value pairs, and it does not maintain any order of elements. Here’s an example of a HashMap and its methods:
import java.util.HashMap; public class Main { public static void main(String[] args) { // Creating a HashMap HashMap<String, Integer> map = new HashMap<>(); // Adding key-value pairs to the HashMap map.put(“Apple”, 1); map.put(“Banana”, 2); map.put(“Cherry”, 3); System.out.println(“Original HashMap: ” + map); // Accessing a value int value = map.get(“Apple”); System.out.println(“Value of Apple: ” + value); // Removing a key-value pair map.remove(“Apple”); System.out.println(“HashMap after removing Apple: ” + map); // Checking if the HashMap contains a key boolean containsBanana = map.containsKey(“Banana”); System.out.println(“Contains Banana? ” + containsBanana); // Checking if the HashMap contains a value boolean containsValue = map.containsValue(2); System.out.println(“Contains value 2? ” + containsValue); // Getting the size of the HashMap int size = map.size(); System.out.println(“Size of HashMap: ” + size); // Updating a value map.put(“Banana”, 20); System.out.println(“HashMap after updating Banana’s value: ” + map); // Clearing the HashMap map.clear(); System.out.println(“HashMap after clearing: ” + map); } } |
The HashMap class in Java provides efficient implementations of various operations, making it a common choice for many applications. Here are the time complexities for the key operations:
- Put (Insertion): The time complexity for the put() method is O(1) in the average case. In the worst-case scenario (when all keys hash to the same bucket), the time complexity degrades to O(n), where n is the number of keys.
- Get (Retrieval): The get() method also has an average time complexity of O(1). Similarly, in the worst-case scenario where all keys hash to the same bucket, it degrades to O(n).
- Remove: The remove() operation, like put() and get(), also has an average time complexity of O(1) and a worst-case time complexity of O(n).
- ContainsKey / ContainsValue: The containsKey() method, which checks if a key is in the map, is similar to get() and has an average time complexity of O(1) and a worst-case time complexity of O(n). However, containsValue() has a time complexity of O(n) in all cases, as it needs to scan through all the entries.
Java HashSet
The HashSet class in Java is a part of the Java Collections Framework. It is used to store unique elements, just like the mathematical concept of a set. It doesn’t maintain any order of its elements.
Here’s an example of HashSet and its methods:
import java.util.HashSet; public class Main { public static void main(String[] args) { // Creating a HashSet HashSet<String> set = new HashSet<>(); // Adding elements to the HashSet set.add(“Apple”); set.add(“Banana”); set.add(“Cherry”); System.out.println(“Original HashSet: ” + set); // Adding a duplicate element set.add(“Apple”); System.out.println(“HashSet after adding a duplicate: ” + set); // Removing an element set.remove(“Apple”); System.out.println(“HashSet after removing Apple: ” + set); // Checking if the HashSet contains an element boolean containsBanana = set.contains(“Banana”); System.out.println(“Contains Banana? ” + containsBanana); // Getting the size of the HashSet int size = set.size(); System.out.println(“Size of HashSet: ” + size); // Clearing the HashSet set.clear(); System.out.println(“HashSet after clearing: ” + set); } } |
In this example, we’re creating a HashSet , adding elements, attempting to add a duplicate element (which is ignored), removing an element, checking if an element exists in the HashSet , getting the size, and finally clearing the set. Remember that HashSet doesn’t maintain any order of its elements. If you need to maintain the insertion order, consider using LinkedHashSet. For sorting the elements in natural order, consider using TreeSet.
Java Iterator
An Iterator is an interface in Java that belongs to the collection framework. It allows us to traverse the collection, access the data element and remove the data elements of the collection.
The Iterator interface has three methods:
- boolean hasNext(): It returns true if Iterator has more elements.
- Object next(): It returns the element and moves the cursor pointer to the next element.
- void remove(): It removes the last elements returned by the iterator. It is less used and not available in all collections.
Here’s an example of how to use an Iterator:
import java.util.ArrayList; import java.util.Iterator; public class Main { public static void main(String[] args) { // Create an ArrayList ArrayList<String> fruits = new ArrayList<String>(); fruits.add(“Apple”); fruits.add(“Banana”); fruits.add(“Cherry”); // Get an iterator Iterator<String> it = fruits.iterator(); // Print the elements using the iterator System.out.println(“Elements in the ArrayList:”); while (it.hasNext()) { String fruit = it.next(); System.out.println(fruit); } // Reset the iterator it = fruits.iterator(); // Remove an element using the iterator while (it.hasNext()) { String fruit = it.next(); if (fruit.equals(“Banana”)) { it.remove(); } } // Print the elements after removal System.out.println(“Elements in the ArrayList after removing Banana:”); it = fruits.iterator(); while (it.hasNext()) { String fruit = it.next(); System.out.println(fruit); } } } |
In this example, we first create an ArrayList and add some elements to it. We then get an Iterator and use it to print the elements in the `ArrayList`. We then use the Iterator to remove the element “Banana”. Finally, we print the elements after the removal to confirm that “Banana” has been removed.
Please note that the remove() operation of an Iterator is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
Java Comparator
In Java, the Comparator interface is used for sorting collections. A Comparator contains a comparison function, which provide an ordering for collections of objects that don’t have a natural ordering. In other words, we can sort the collection on the basis of multiple elements such as sort by id, name, and price etc.
The Comparator interface is found in the java.util package. It consists of two methods: compare(Object obj1, Object obj2) and equals(Object element).
- The compare(Object obj1, Object obj2) method compares obj1 and obj2. The method returns a negative integer if obj1 is less than obj2(obj1 < obj2), returns 0 if obj1 is equal to obj2, and a positive integer if obj1 is greater than obj2.
- The equals(Object element) method simply checks if the Comparator is equal to the element argument.
Here’s an example of using a comparator to sort a list of integers in descending order:
import java.util.Arrays; import java.util.Comparator; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(5, 1, 3, 7, 2); numbers.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 – o1; // For descending order } }); // What is the type of this parameter? object with Comparator type. System.out.println(numbers); // Output: [7, 5, 3, 2, 1] } } |
Comparator can also be defined using lambda expressions.
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(5, 1, 3, 7, 2); numbers.sort((o1, o2) -> o2 – o1); // For descending order System.out.println(numbers); // Output: [7, 5, 3, 2, 1] } } |
In each of these examples, we’re using a different approach to define a Comparator that sorts integers in descending order. The anonymous class approach provides the most flexibility but is also the most verbose. The lambda expression approach is more concise.