import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

class Employee implements Comparable<Employee> {
    private final int id;
    private final String name;

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        // Force hash collision for all Employee objects
        return 42;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Employee employee = (Employee) obj;
        return id == employee.id && name.equals(employee.name);
    }

    @Override
    public String toString() {
        return "Employee{id=" + id + ", name='" + name + "'}";
    }

    @Override
    public int compareTo(Employee o) {
        return 1; // This line brings the unpredictable behaviour.
    }
}

public class HashMapTreeifyExample {
    public static void main(String[] args) throws Exception {
        // Set initial capacity to at least 64 to prevent resizing
        Map<Employee, String> map = new HashMap<>(64);
        ArrayList<Employee> list = new ArrayList<>();
        // Add 10 Employee-Address pairs to the same bucket
        for (int i = 1; i <= 10; i++) {
            Employee employee = new Employee(i, "Employee" + i);
            String address = "Address" + i;
            map.put(employee, address);
            System.out.println("Adding: " + employee + ". Size=" + map.size() + ". "+ printTreeOrLinkedList(map));
            list.add(employee);
        }

        System.out.println("\n\n################################");
        System.out.println("Print all the HashMap entries");
        map.forEach((key, value) -> {
            System.out.println(key + " -> " + value);
        });

        System.out.println("\n\n################################");
        System.out.println("Search all the HashMap entries");
        for (Employee e : list) {
            System.out.println(e + "-" + map.get(e));
        }

        System.out.println("\n\n################################");
        System.out.println("Remove all the HashMap entries");
        for(Employee employee :list){
            map.remove(employee);
            System.out.println("Removing: " + employee + ". Size=" + map.size() + ". "+ printTreeOrLinkedList(map));
        }

        System.out.println("\n\n################################");
        System.out.println("Print all the HashMap entries. HashMap should be empty now.");
        map.forEach((key, value) -> {
            System.out.println(key + " -> " + value);
        });

        System.out.println("\n\n################################");
        System.out.println("Search all the HashMap entries. No etries should be found because we removed everything.");
        for (Employee e : list) {
            System.out.println(e + "-" + map.get(e));
        }


    }

    static <K,V> String printTreeOrLinkedList(Map<K, V> map) throws Exception{
        String value = "Bucket:";
        Field tableField = HashMap.class.getDeclaredField("table");
        tableField.setAccessible(true);

        // Get the table array from the HashMap
        Object[] table = (Object[]) tableField.get(map);

        // Iterate over the table array
        for (Object bucket : table) {
            if (bucket != null) {
                value += bucket.getClass().getName();
            }
        }
        return value;
    }
}