Skip to content

Weird Java & Kotlin Notes


Logo

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

Gmail  GitHub  LinkedIn  Facebook  Instagram  Twitter

📔 Table of Contents
  1. 📄 About The Project
    1a
🔖 Java
  1. 📄 Get An Array Of Map's Keys
    1a-J
  2. 📄 Swap Keys And Values In A Map
    2a-J
  3. 📄 Convert Array Of Primitives To A List Or Set
    3a-J
  4. 📄 Compare Wrapper Types
    4a-J
  5. 📄 Nest Methods
    5a-J
  6. 📄 Map Two Arrays To A HashMap
    6a-J
  7. 📄 Store Key-Value Pairs In A List
    7a-J
  8. 📄 Create A Node Priority Queue With Comparator
    8a-J
    8b-J
  9. 📄 Create A HashSet Of Arrays
    9a-J
  10. 📄 Lexicographically Sort A 2D List
    10a-J
  11. 📄 Iterate Through A HashMap
    11a-J
  12. 📄 Map Characters To An Array
    12a-J

About The Project

Banner

   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.

👉 📒

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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).

(back to top ⤴️)

   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).

(back to top ⤴️)

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).

(back to top ⤴️)

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.

(back to top ⤴️)

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.

(back to top ⤴️)

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).

(back to top ⤴️)