Weird Java & Kotlin Notes
Weird Java & Kotlin Notes
My lifelong notes about the weird 😵💫 and wild 🤪 features of Java & Kotlin!
Explore the docs »
Explore the docs (Kotlin) »
Stream API Docs
·
Java 8 Cheat Sheet
·
Stream API Cheat Sheet
📔 Table of Contents
🔖 Java
- 📄 Get An Array Of Map's Keys
- 📄 Swap Keys And Values In A Map
- 📄 Convert Array Of Primitives To A List Or Set
- 📄 Compare Wrapper Types
- 📄 Nest Methods
- 📄 Map Two Arrays To A HashMap
- 📄 Store Key-Value Pairs In A List
- 📄 Create A Node Priority Queue With Comparator
- 📄 Create A HashSet Of Arrays
- 📄 Lexicographically Sort A 2D List
- 📄 Iterate Through A HashMap
- 📄 Map Characters To An Array
About The Project
Hello! I'm Colston D. Bod-oy; I'm a React and Android developer, and I would be taking my 3rd year of college at the time that I made this repo. I'm an aspiring developer, and I would like to work for the big FAANG companies someday 😉.
I created this project so I could keep track of and recall things that I didn't know I could do in Java and Kotlin, as I've just recently started learning them on a deeper level. I hope you'll find these notes useful! 😎.
README Template
Btw, here's where I got this template. Also, don't forget to follow me on my social media links.
👉 📒
Get An Array Of Map's Keys
I found these examples on Stack Overflow, which converts a set of map keys into an array.
1a-J Example
import java.util.Arrays;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> stringsMap = new HashMap<>();
stringsMap.put("!V$q", 16087526);
stringsMap.put("lW@$", 64992058);
stringsMap.put("V*tx", 61656601);
stringsMap.put("W*Ru", 77778805);
stringsMap.put("b#Oo", 44708273);
HashMap<Integer, String> integersMap = new HashMap<>();
integersMap.put(16087526, "!V$q");
integersMap.put(64992058, "lW@$");
integersMap.put(61656601, "V*tx");
integersMap.put(77778805, "W*Ru");
integersMap.put(44708273, "b#Oo");
HashMap<String, String> strNumsMap = new HashMap<>();
strNumsMap.put("16087526", "!V$q");
strNumsMap.put("64992058", "lW@$");
strNumsMap.put("61656601", "V*tx");
strNumsMap.put("77778805", "W*Ru");
strNumsMap.put("44708273", "b#Oo");
// Output: [!V$q, b#Oo, lW@$, W*Ru, V*tx]
System.out.println(Arrays.toString(stringsMap
.keySet().stream().toArray()));
// Output: [16087526, 64992058, 61656601, 77778805, 44708273]
System.out.println(Arrays.toString(integersMap
.keySet().stream().mapToInt(Integer
::intValue).toArray()));
// Output: [61656601, 44708273, 77778805]
System.out.println(Arrays.toString(Arrays
.copyOfRange(strNumsMap.keySet().stream()
.mapToInt(Integer::parseInt).toArray(),
0, 3)));
}
}
1a-J Description
We used the keySet()
method of the HashMap
class to get a set view of the keys contained in our map, then we created a new stream from those keys so we could apply common stream operations like mapToInt()
which maps a stream to an IntStream
where we could also do things like Integer.intValue()
which returns the value of the specified Integer
object as an int
primitive data type.
We also used Integer.parseInt()
on the last example to return an int
from a given string representation and applied Arrays.copyOfRange()
to it so that the resulting array would only contain the first 3 keys of our map. For all our examples, we used the toArray()
method at the end to get an array of all the elements of the IntStream
.
Swap Keys And Values In A Map
I found these examples on Stack Overflow, which swap the keys and values contained in a map. I also got additional information about the Collectors.groupingBy()
method on Stack Abuse.
2a-J Example
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> cityMap = new HashMap<>();
cityMap.put("New York", 20220928);
cityMap.put("Chicago", 20220812);
cityMap.put("Boston", 20220928);
cityMap.put("Los Angeles", 20220928);
cityMap.put("Seattle", 20221103);
Map<Integer, List<String>> dateMap = cityMap
.entrySet().stream().collect(Collectors
.groupingBy(Map.Entry::getValue, Collectors
.mapping(Map.Entry::getKey, Collectors.toList())));
TreeMap<Integer, List<String>> sortedDateMap = cityMap
.entrySet().stream().collect(Collectors
.groupingBy(Map.Entry::getValue, TreeMap::new,
Collectors.mapping(Map.Entry::getKey,
Collectors.toList())));
/*
* Output:
* {20220928=[New York, Los Angeles, Boston],
* 20220812=[Chicago], 20221103=[Seattle]}
*/
System.out.println(dateMap);
/*
* Output:
* {20220812=[Chicago],
* 20220928=[New York, Los Angeles, Boston],
* 20221103=[Seattle]}
*/
System.out.println(sortedDateMap);
}
}
2a-J Description
First, the set view of the mappings was obtained to create a new stream, and then we applied the Stream.collect()
method, which performed a mutable reduction operation on the elements of the stream. A mutable reduction operation collects input elements into a mutable container, such as a Collection
, as it processes the elements of the stream.
We use the Collectors.groupingBy()
method to return a Collector
that groups objects by a given specific property and stores the end result in a map. The Collector
makes a Map<K, List<T>>
, whose keys are the values resulting from applying the classification function to the input elements. Each value of those keys is a List
containing the input elements, which map to the associated key.
In the first example, we used Entry.getValue()
as our classification function and Collectors.mapping()
to apply a reduction operation to the values associated with a given key. Using Entry.getKey()
as our mapping function, we're able to reduce our data to only use keys as values. Finally, Collectors.toList()
was used as the downstream collector to accept the mapped values.
By doing all of the operations, we ended up with a Map
instance that has the swapped key-value pairs from the initial map. Notice how we have duplicate values from our previous map, so when they're converted to keys, each of their previously associated keys is added inside a List
. The second example was pretty much the same as the first; the only difference is that we've added a supplier method, TreeMap::new
, which specifies the exact implementation of Map
we want to use. This time it uses a TreeMap
implementation, so the keys for our new map are automatically sorted.
Convert Array Of Primitives To A List Or Set
The information I used for these examples can be found on HowToDoInJava, which allows me to create a List
or a Set
from a stream of primitives.
3a-J Example
import java.util.List;
import java.util.Arrays;
import java.util.HashSet;
import java.util.stream.Collectors;
class Main {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
HashSet<Integer> set = new HashSet<>(Arrays
.stream(nums).boxed().collect(Collectors.toSet()));
List<Integer> list = Arrays.stream(nums)
.boxed().collect(Collectors.toList());
// Output: [1, 2, 3, 4, 5]
System.out.println(set);
// Output: [1, 2, 3, 4, 5]
System.out.println(list);
}
}
3a-J Description
The array was first converted to a stream, and since it's a stream of primitives, we also needed to use the boxed()
method to return a stream consisting of the elements of the given stream, each boxed to an object of the corresponding wrapper class, Integer
in this case. Then we just apply the Stream.collect()
method to create a List
or use the result inside a constructor like the one from HashSet
.
Compare Wrapper Types
The information I used for these examples can be found on Stack Overflow, which shows why the Integer
objects are not equal.
4a-J Example
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<Character, Integer> map1 = new HashMap<>();
HashMap<Character, Integer> map2 = new HashMap<>();
map1.put('N', 127);
map2.put('N', 127);
// Output: true
System.out.println(map1.get('N')
== map2.get('N'));
map1.put('N', 128);
map2.put('N', 128);
// Output: false
System.out.println(map1.get('N')
== map2.get('N'));
// Output: true
System.out.println(map1.get('N')
.equals(map2.get('N')));
Integer num = new Integer(2);
// Output: false
System.out.println(num == Integer.valueOf(2));
}
}
4a-J Description
When comparing wrapper types such as Integer
, Long
, or Boolean
, use ==
or !=
, we're comparing them as references, not as values. The first example produces a value of true
because in Java, numeric values within the range of -128 to 127 are cached, so they would have an identical memory location. For Integer
, use intValue()
, compareTo()
, or equals()
when making comparisons. If using wrapper classes like Integer
can't be avoided, we can use the Integer.valueOf()
method, which guarantees, as per the Java specs, the reuse of the first 256 Integer
objects from -128 to 127, while new Integer()
forces the creation of a new object, as shown in the last example.
Nest Methods
The information I used for these examples can be found on GeeksforGeeks, which shows the different ways we could nest methods in Java.
5a-J Example
class Main {
interface Build {
int factorial(int n);
}
public static void buildStr() {
StringBuilder sb = new StringBuilder(5);
Build builder = new Build() {
@Override
public int factorial(int n) {
if (n == 0 || n == 1) {
return 1;
}
return n * factorial(n - 1);
};
};
for (int i = 0; i < 5; i++) {
sb.append(builder.factorial(i));
}
System.out.println(sb.toString());
}
public static void main(String[] args) {
// Output: 112624
buildStr();
}
}
5a-J Description
Java does not support nested methods, so we used an anonymous subclass from the example above to achieve a similar structure. An anonymous class is an inner class without a name that usually extends subclasses or implements interfaces, and only a single object can be created from it.
Map Two Arrays To A HashMap
The information I used for these examples can be found on Stack Overflow Link 1 and Stack Overflow Link 2, which allow sorting of the map as well.
6a-J Example
import java.util.Map;
import java.util.TreeMap;
import java.util.LinkedHashMap;
import java.util.stream.IntStream;
import java.util.function.Supplier;
import static java.util.Comparator.comparing;
import static java.util.Comparator.reverseOrder;
import static java.util.stream.Collectors.toMap;
class Main {
public static void main(String[] args) {
int[] positions = {10, 8, 0, 5, 3};
int[] speeds = {2, 4, 1, 1, 3};
Map<Integer, Integer> velocities = IntStream
.range(0, positions.length).boxed()
.collect(toMap(i -> positions[i],
i -> speeds[i]));
Map<Integer, Integer> velocitiesOrdered = IntStream
.range(0, positions.length).boxed()
.collect(toMap(i -> positions[i],
i -> speeds[i],
(i, j) -> i,
LinkedHashMap::new));
Map<Integer, Integer> velocitiesSorted = IntStream
.range(0, positions.length).boxed()
.sorted(comparing(i -> positions[i]))
.collect(toMap(i -> positions[i],
i -> speeds[i],
(i, j) -> i,
LinkedHashMap::new));
Supplier<TreeMap<Integer, Integer>> mapSupplier = ()
-> new TreeMap<>(reverseOrder());
Map<Integer, Integer> velocitiesReverseSorted = IntStream
.range(0, positions.length).boxed()
.collect(toMap(i -> positions[i],
i -> speeds[i],
(i, j) -> i,
mapSupplier));
Map<Integer, Integer> velocitiesSpeedSorted = IntStream
.range(0, positions.length).boxed()
.sorted(comparing(i -> speeds[i]))
.collect(toMap(i -> positions[i],
i -> speeds[i],
(i, j) -> i,
LinkedHashMap::new));
// Output: {0=1, 3=3, 5=1, 8=4, 10=2}
System.out.println(velocities);
// Output: {10=2, 8=4, 0=1, 5=1, 3=3}
System.out.println(velocitiesOrdered);
// Output: {0=1, 3=3, 5=1, 8=4, 10=2}
System.out.println(velocitiesSorted);
// Output: {10=2, 8=4, 5=1, 3=3, 0=1}
System.out.println(velocitiesReverseSorted);
// Output: {0=1, 5=1, 10=2, 3=3, 8=4}
System.out.println(velocitiesSpeedSorted);
}
}
6a-J Description
To use the Collectors.toMap()
method, we have to box the int
primitives into Integer
objects first. To preserve the element order, use the extended version of Collectors.toMap()
together with the LinkedHashMap::new
function as the argument for the mapSupplier
parameter, which was shown in the second example.
For the third example, we used the Comparator.comparing
method to compare values from the positions array and sort them in ascending order; note how we also used the LinkedHashMap::new
function for this example and the fifth example to maintain the sorted values when collecting them into a map.
We created a TreeMap
with a Comparator.reverseOrder
and used it as the mapSupplier
for the fourth example to get a hashmap that has a descending order based on the values of the position array. Finally, we used the speed array as the basis for the sorting of the fifth example.
Store Key-Value Pairs In A List
The information I used for these examples can be found on Techie Delight, which shows how to implement a Pair
class.
7a-J Example
import java.util.List;
import java.util.Arrays;
import java.util.HashMap;
import java.util.ArrayList;
class Main {
class Pair<T, V> {
private final T key;
private final V value;
public Pair(T key, V value) {
this.key = key;
this.value = value;
}
public T getKey() {
return key;
}
public V getValue() {
return value;
}
}
class TimeMap {
HashMap<String, List<Pair<String, Integer>>> map;
public TimeMap() {
map = new HashMap<>();
}
public void set(String key, String value, int timestamp) {
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(new Pair(value, timestamp));
}
public String get(String key) {
String res = "";
List<Pair<String, Integer>> list = map
.getOrDefault(key, new ArrayList<>(0));
for (Pair<String, Integer> p : list) {
res += "[" + p.getKey() + ", "
+ p.getValue() + "] ";
}
return res;
}
}
public static void main(String[] args) {
Main main = new Main();
Main.TimeMap map = main.new TimeMap();
map.set("Server1", "User1", 145);
map.set("Server1", "User2", 565);
map.set("Server1", "User3", 35);
map.set("Server1", "User4", 13);
map.set("Server1", "User5", 145);
map.set("Server2", "User1", 23);
map.set("Server2", "User2", 19);
map.set("Server2", "User3", 61);
/*
* Output:
* [User1, 145] [User2, 565] [User3, 35]
* [User4, 13] [User5, 145]
*/
System.out.println(map.get("Server1"));
// Output: [User1, 23] [User2, 19] [User3, 61]
System.out.println(map.get("Server2"));
}
}
7a-J Description
Java's List
does not support key-value pairs, so we have to create a Pair
custom class to be able to store them as elements. We can do this by using generics, so we can use different kinds of data for our keys and values. The created List
would then be used by our HashMap
to store values while also assigning its own key, as shown in the examples.
Create A Node Priority Queue With Comparator
The information I used for these first examples can be found on GitHub, which is the Java solution for the LeetCode problem K Closest Points to Origin.
8a-J Example
import java.util.Arrays;
import java.util.PriorityQueue;
class Main {
public int[][] kClosestMinHeap(int[][] points, int k) {
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b)
-> Double.compare(Math.pow(a[0], 2)
+ Math.pow(a[1], 2),
Math.pow(b[0], 2)
+ Math.pow(b[1], 2)));
for (int[] point : points) {
pq.offer(point);
}
int[][] res = new int[k][2];
for (int i = 0; i < k; i++) {
int[] cur = pq.poll();
res[i][0] = cur[0];
res[i][1] = cur[1];
}
return res;
}
public int[][] kClosestMaxHeap(int[][] points, int k) {
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b)
-> Double.compare(Math.pow(b[0], 2)
+ Math.pow(b[1], 2),
Math.pow(a[0], 2)
+ Math.pow(a[1], 2)));
for (int[] point : points) {
pq.offer(point);
if (pq.size() > k) {
pq.poll();
}
}
int[][] res = new int[k][2];
for (int i = 0; i < k; i++) {
int[] cur = pq.poll();
res[i][0] = cur[0];
res[i][1] = cur[1];
}
return res;
}
public static void main(String[] args) {
Main main = new Main();
int[][] points = {{3, 3}, {5, -1}, {-2, 4}};
// Output: [[3, 3], [-2, 4]]
System.out.println(Arrays.deepToString(main
.kClosestMinHeap(points, 2)));
// Output: [[-2, 4], [3, 3]]
System.out.println(Arrays.deepToString(main
.kClosestMaxHeap(points, 2)));
}
}
8a-J Description
The examples above return the k closest points to the origin of an X-Y plane (0, 0) from a given set of coordinates. To solve the problem, we'll use a heap binary tree data structure, which is implemented as the PriorityQueue
in Java. We could then pass a Comparator
when instantiating to give rules on how we would want to order the elements that would be stored inside the PriorityQueue
.
Instead of creating a new Comparator
object, we could just use Java 8's lambda expression feature to declare how our comparisons would work. We also used the Euclidean formula to calculate the distance of the points from the origin (note that we didn't apply the square root to the formula because it wouldn't affect our desired results). In the first example, we created what's called a min heap because the points would be ordered in an ascending order based on the results of the formula. We then continuously popped the head of the PriorityQueue
and assigned its values to the indexes of our res
2D array until we had enough k elements, which we would then finally return as our result.
We could save more space by using a max heap instead of a min heap, as shown in the second example; we were able to convert the Comparator
for the max heap by flipping the conditions where we have the second array in our lambda expression as the first argument in our Double.compare()
method (note that we used Double
instead of Integer
because the Math.pow()
method returns a double
value).
The information I used for the next examples can be found on Stack Overflow Link 1, which shows why using the commented line (see code below) would cause an overflow when trying to get the difference of two large arbitrary signed integers, thus causing unexpected behaviors. Stack Overflow Link 2 shows how to implement the Comparable
interface to avoid such problems.
8b-J Example
import java.util.PriorityQueue;
class Main {
class ListNode implements Comparable<ListNode> {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
@Override
public int compareTo(ListNode n) {
if (this.val < n.val) {
return -1;
} else if (this.val > n.val) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
String result = val + " -> ";
if (next != null) {
result += next.toString();
}
return result;
}
}
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
// PriorityQueue<ListNode> queue = new PriorityQueue<>((a, b)
// -> a.val - b.val);
PriorityQueue<ListNode> queue = new PriorityQueue<>((a, b)
-> a.compareTo(b));
for (ListNode n : lists) {
if (n != null) {
queue.offer(n);
}
}
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
while (!queue.isEmpty()) {
ListNode n = queue.poll();
curr.next = n;
curr = curr.next;
if (n.next != null) {
queue.offer(n.next);
}
}
return dummy.next;
}
public static void main(String[] args) {
Main main = new Main();
// List Node 1
Main.ListNode list1Tail = main.new ListNode(5);
Main.ListNode list1N = main.new ListNode(4, list1Tail);
Main.ListNode list1Head = main.new ListNode(1, list1N);
// List Node 2
Main.ListNode list2Tail = main.new ListNode(4);
Main.ListNode list2N = main.new ListNode(3, list2Tail);
Main.ListNode list2Head = main.new ListNode(1, list2N);
// List Node 3
Main.ListNode list3Tail = main.new ListNode(6);
Main.ListNode list3Head = main.new ListNode(2, list3Tail);
ListNode[] lists = {list1Head, list2Head, list3Head};
ListNode mergedListsHead = main.mergeKLists(lists);
// Output: 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6 ->
System.out.println(mergedListsHead.toString());
}
}
8b-J Description
The example above merges sorted list nodes together, where List Nodes 1 and 2 have three nodes while List Node 3 only has a head and a tail. We can implement the code in two ways, but the commented line does not work in general because there's a chance that it would cause an overflow when the variable a
in the lambda expression is a large positive number while the b
variable is a large negative number, resulting in having to add the two large numbers together, which the int
data type might not be able to hold, and the answer would instead be a negative integer instead of a positive one, giving the opposite of the intended behavior.
To solve the previous problem, we must implement the Comparable
interface on our ListNode
class, which allows us to implement our own compareTo
function without having to subtract two integers to get a positive or negative result.
This method of creating a comparator for the PriorityQueue
is preferred over the examples in 9a when the elements used are not Comparable
out of the box (e.g., custom classes).
Create A HashSet Of Arrays
The information I used for this example can be found on Stack Overflow, which shows different ways to implement a HashSet
containing arrays or collections as elements.
9a-J Example
import java.util.List;
import java.util.HashSet;
class Main {
public static void main(String[] args) {
int x = 0;
int y = 1;
int[] arr1 = {x, y};
int[] arr2 = {x, y};
List<Integer> list1 = List.of(x, y);
List<Integer> list2 = List.of(x, y);
HashSet<int[]> set1 = new HashSet<>();
HashSet<List<Integer>> set2 = new HashSet<>();
set1.add(arr1);
// Output: false
System.out.println(set1.contains(arr2));
set2.add(list1);
// Output: true
System.out.println(set2.contains(list2));
}
}
9a-J Description
In the above example, we're creating two HashSet
objects, one of which accepts int[]
elements while the other accepts List<Integer>
. Since int[]
is not a primitive data type, when creating a new array from the x
and y
variables and then invoking the contains
function of set1
, the default behavior of the function would be to compare the reference of the objects instead of their contents, which is why we're getting a false
result. To fix this, we can use a List
instead of an array because it's an object that implements the equals()
method based on its contents (note that set2
uses more space since it stores Integer
objects; check this link for a better implementation that uses a custom class).
Lexicographically Sort A 2D List
The information I used for this example can be found on Stack Overflow, which shows how to sort a 2D array that has two elements per array lexicographically using Java 8's lambda function to create a Comparator
.
10a-J Example
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
List<List<String>> tickets = new ArrayList<>(List
.of(List.of("JFK", "SFO"),
List.of("ATL", "JFK"),
List.of("SFO", "ATL"),
List.of("JFK", "ATL"),
List.of("ATL", "SFO")));
/*
* Output:
* [[JFK, SFO], [ATL, JFK], [SFO, ATL],
* [JFK, ATL], [ATL, SFO]]
*/
System.out.println(Arrays
.deepToString(tickets.toArray()));
Collections.sort(tickets, (a, b) -> {
if (a.get(0).equals(b.get(0))) {
return a.get(1).compareTo(b.get(1));
}
return a.get(0).compareTo(b.get(0));
});
/*
* Output:
* [[ATL, JFK], [ATL, SFO], [JFK, ATL],
* [JFK, SFO], [SFO, ATL]]
*/
System.out.println(Arrays
.deepToString(tickets.toArray()));
}
}
10a-J Description
In the above example, we're trying to sort a 2D List
of tickets that contains the abbreviations of states for the source location and destination pairs. We'll sort the tickets in lexicographical order based on their source location, and if they're exactly the same, their destination will be used instead. We used the Collections.sort()
method to sort the List
of tickets and provided it with a Comparator
in the form of a lambda expression that has the logic that allows us to compare the second elements of the ticket lists if their first elements are the same.
Iterate Through A HashMap
The information I used for this example can be found on Stack Overflow, which shows different ways to iterate through the elements of a HashMap
.
11a-J Example
import java.util.Map;
import java.util.HashSet;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
String alienWord = "wertf";
HashMap<Character, HashSet<Character>> charMap
= new HashMap<>();
for (int i = 0; i < alienWord.length() - 1; i++) {
for (char letter : alienWord.substring(i + 1)
.toCharArray()) {
charMap.computeIfAbsent(alienWord.charAt(i),
k -> new HashSet<>())
.add(letter);
}
}
/*
* Output:
* r: [t, f]
* t: [f]
* e: [r, t, f]
* w: [r, t, e, f]
*/
for (Map.Entry<Character, HashSet<Character>> set
: charMap.entrySet()) {
System.out.println(set.getKey() + ": "
+ set.getValue());
}
// Output: r t e w
for (char c : charMap.keySet()) {
System.out.print(c + " ");
}
/*
* Output:
* r: [t, f]
* t: [f]
* e: [r, t, f]
* w: [r, t, e, f]
*/
charMap.forEach((k, v)
-> System.out.println(k + ": " + v));
}
}
11a-J Description
In the above example, we're trying to map the characters of the alienWord
variable to its substrings and print them out as the contents of a HashMap
. We can do this by using the entrySet()
method of our HashMap
, which returns a Set
view of the mappings that we can iterate over, as shown in the first example, while the second example shows how we can iterate only in the keys by using the keySet()
method, and the last example shows how we can do the first example using Java 8's lambda function.
Map Characters To An Array
The information I used for this example can be found on GeeksforGeeks, which shows how to sort a string of characters by using the following method, and Stack Overflow, which shows how to convert an integer to a character.
12a-J Example
class Main {
public static void main(String[] args) {
String alienWord = "wertf";
boolean[] alphabets = new boolean[26];
for (char c : alienWord.toCharArray()) {
alphabets[c - 'a'] = true;
}
// Output: efrtw
for (int i = 0; i < alphabets.length; i++) {
if (alphabets[i]) {
System.out.print((char) (i + '0' + 49));
}
}
}
}
12a-J Description
In the above example, we're trying to map the characters of the alienWord
variable to an array by converting them to integers, which would serve as their index on the array. We can do this by subtracting their ASCII
numeric value from that of the character 'a'
, so 'a' - 'a'
would yield a result of zero, meaning that the boolean
value that represents whether or not that character exists in the alienWord
variable would be stored at that index in the array (note that our array has a fixed size of 26
since there are only 26
letters in the English alphabet), which has a default value of false
and would be set to true
as the resulting index was accessed in the array.
Once all of the array indexes correlating to characters in the word have been marked true
, the program would convert said indexes back to their character equivalent by adding to them the ASCII
numeric value of '0'
and increasing the result by 49
to get back the ASCII
numeric value of the character 'a'
onwards. For example, 0 + '0'
is equal to 48
, and adding 49
to it would result in 97
, which is the ASCII
value for the character 'a'
(note that the resulting string printed doesn't have the exact same order as the original one since the characters are mapped to their equivalant index based on their position on the English alphabet).