Showing posts with label map. Show all posts
Showing posts with label map. Show all posts

Wednesday, 10 April 2024

Creating Case-Insensitive Maps in Java: Simplifying Lookups with Lowercase Keys

In software development, particularly in Java, there are situations where case sensitivity in data lookups can be a trouble. Consider scenarios where you need to retrieve values from a collection, such as a Map, where the keys may vary in their case sensitivity. To address this issue, developers often depends on solutions like case-insensitive maps.

 


A case-insensitive map is a data structure that enables developers to perform lookups without considering the case of the keys. In this context, all keys are converted to lowercase strings, ensuring uniformity in the lookup process. However, it's crucial to maintain the original keys intact for preserving data integrity and reference.

 

Use Cases:

1.   User Authentication: When dealing with user authentication systems, usernames often need to be case insensitive. A case-insensitive map can be employed to store user credentials, allowing users to log in regardless of the case used in their usernames.

2.   Configuration Management: In applications where configuration settings are stored in a map-like structure, a case-insensitive map can ensure consistency in accessing these settings. Developers can retrieve configuration values without worrying about the case sensitivity of the keys.

3.   URL Routing in Web Applications: Web applications often handle URLs where the paths may vary in case sensitivity. By utilizing a case-insensitive map to store route mappings, developers can efficiently route incoming requests to the appropriate handlers without considering the case of the URLs.

4.   Data Processing and Filtering: In data processing tasks, especially when dealing with textual data, a case-insensitive map can be invaluable. It allows for efficient filtering and retrieval of data based on case-insensitive criteria, enhancing the robustness and usability of data processing pipelines.

 

By incorporating case-insensitive maps into the Java applications, developers can simplify data lookups, improve system reliability, and enhance overall user satisfaction by providing a seamless and intuitive experience, irrespective of the case sensitivity of the input data.

 

Find the sample implementation of Case insensitive map.

 

CaseInsensitiveHashMap.java

package com.sample.app.collections.map;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class CaseInsensitiveHashMap extends HashMap<String, Object> {
	private static final long serialVersionUID = 123291348765l;

	private final Map<String, String> lowerCaseMap = new HashMap<>();

	public CaseInsensitiveHashMap(final int initialCapacity) {
		super(initialCapacity);
	}

	@Override
	public boolean containsKey(final Object key) {
		final Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
		return super.containsKey(realKey);
	}

	@Override
	public Object get(final Object key) {
		final Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
		return super.get(realKey);
	}

	@Override
	public Object put(final String key, final Object value) {
		final Object oldKey = lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key);
		final Object oldValue = super.remove(oldKey);
		super.put(key, value);
		return oldValue;
	}

	@Override
	public void putAll(final Map<? extends String, ?> m) {
		m.forEach(this::put);
	}

	@Override
	public Object remove(final Object key) {
		final Object realKey = lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH));
		return super.remove(realKey);
	}
}

CaseInsensitiveHashMapDemo.java

package com.sample.app;

import java.util.Map;

import com.sample.app.collections.map.CaseInsensitiveHashMap;

public class CaseInsensitiveHashMapDemo {
	public static void main(String[] args) {
		Map<String, Object> map = new CaseInsensitiveHashMap(10);
		
		map.put("India", "New Delhi");
		map.put("Japan", "Tokyo");
		
		System.out.println("Capital of India is :");
		System.out.println(map.get("India"));
		System.out.println(map.get("INDIA"));
		System.out.println(map.get("INDia"));
		
		
	}

}

Output

Capital of India is :
New Delhi
New Delhi
New Delhi



You may like

Interview Questions

Utility class to get primitive type from wrapper type and vice versa

FNV hash algorithm implementation in Java

Controlling Randomness in Java: Exploring the Role of Seeds in java.util.Random

Calculating initial capacity from expected size and load factor

A Beginner's Guide to UUID Types

Ensuring Platform-Independent Accuracy: A Guide to strictfp in Java

Friday, 3 November 2023

Calculating initial capacity from expected size and load factor

 Problem statement: If you had given expected size and load factor, can you improve the performance of HashMap

 

Let's talk about capacity and load factor before addressing the problem statement here.

 

Capacity

Capacity specifies the number of elements in a HashMap can store before it needs to be resized.

 

Load Factor

When the load factor of a HashMap exceeds a certain threshold, then it is resized to avoid performance problems. This process is called rehashing. In Rehashing procedure, a new HashMap with a larger capacity is created, and move all of the elements from the old HashMap to the new HashMap.

 

The default load factor is 0.75, that means when the HashMap reaches 75% of the capacity it will be resized.

 

Why choosing right capacity and load factor is important?

Choosing a wring capacity and load factor will impact the performance.

 

a.   If the capacity is too small, then the HashMap will need to be resized frequently.

b.   If the capacity is too large, the hash table will be wasting space.

 

Now, let’s talk about the problem statement, since we have given expected size and load factor, we can calculate initial capacity and construct the HashMap with calculated initial capacity to get rid of resizing and more space issues.

private static int calculateCapacity(int totalEntries) {
	return calculateCapacity(totalEntries, 0.75d);
}

If we have some idea on the approximate entries, then we can use ‘calculateCapacity’ method to get the approximate initial capacity of the HashMap.

 

Find the below working application.

 


MapUtil.java

package com.sample.app.util;

import java.util.HashMap;

public class MapUtil {
	private static int calculateCapacity(int totalEntries) {
        return calculateCapacity(totalEntries, 0.75d);
    }
	
	private static int calculateCapacity(int totalEntries, double loadFactor) {
        return (int) Math.ceil(totalEntries / loadFactor);
    }
	
	public static <K, V> HashMap<K, V> newHashMap(int totalEntries) {
        return new HashMap<>(calculateCapacity(totalEntries));
    }
	
	
}

App.java

package com.sample.app;

import java.util.*;

import com.sample.app.util.MapUtil;

public class App {

	private static void testApp() {
		int totalEntries = 1000000;

		System.out.println("For the entries : " + totalEntries);
		for (int i = 0; i < 10; i++) {

			long time1 = System.currentTimeMillis();

			Map<Integer, Object> map1 = new HashMap<>();
			for (int j = 0; j < totalEntries; j++) {
				map1.put(j, new Object());
			}

			long time2 = System.currentTimeMillis();

			Map<Integer, Object> map2 = MapUtil.newHashMap(totalEntries);
			for (int j = 0; j < totalEntries; j++) {
				map2.put(j, new Object());
			}

			long time3 = System.currentTimeMillis();

			System.out.println("\tFor default map : " + (time2 - time1));
			System.out.println("\tFor capacity calcualted map : " + (time3 - time2));
			System.out.println();
			
			System.gc();

		}

	}

	public static void main(String[] args) {
		testApp();
	}

}

Output

For the entries : 1000000
	For default map : 115
	For capacity calcualted map : 55

	For default map : 31
	For capacity calcualted map : 67

	For default map : 24
	For capacity calcualted map : 42

	For default map : 21
	For capacity calcualted map : 13

	For default map : 20
	For capacity calcualted map : 10

	For default map : 20
	For capacity calcualted map : 11

	For default map : 20
	For capacity calcualted map : 10

	For default map : 22
	For capacity calcualted map : 9

	For default map : 21
	For capacity calcualted map : 9

	For default map : 21
	For capacity calcualted map : 10



 

You may like

Interview Questions

Program to create append only log file in Java

Implement retry handler for a task in Java

Design an utility class to capture application metrics summary in Java

Utility class to get primitive type from wrapper type and vice versa

FNV hash algorithm implementation in Java

Controlling Randomness in Java: Exploring the Role of Seeds in java.util.Random

Thursday, 18 May 2023

Construct a map from array of objects using streams

Below snippet get the map from employees array, where key is the employee id and object is employee itself.

Map<Integer, Employee> empById = unmodifiableMap(Arrays.stream(emps).collect(Collectors.toMap(Employee::getId, identity())));

Find the below working application.

 

MapFromArray.java

package com.sample.app.collections;

import static java.util.Collections.unmodifiableMap;
import static java.util.function.Function.identity;

import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class MapFromArray {

    private static class Employee {
        private int id;
        private String name;

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

        public int getId() {
            return id;
        }

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

    }

    public static void main(String[] args) {
        Employee emp1 = new Employee(1, "Krishna");
        Employee emp2 = new Employee(2, "Krishna");
        Employee emp3 = new Employee(3, "Krishna");
        Employee emp4 = new Employee(4, "Krishna");

        Employee[] emps = { emp1, emp2, emp3, emp4 };

        Map<Integer, Employee> empById = unmodifiableMap(
                Arrays.stream(emps).collect(Collectors.toMap(Employee::getId, identity())));

        for (Entry<Integer, Employee> entry : empById.entrySet()) {
            System.out.println(entry.getKey() + "\t" + entry.getValue());
        }
    }

}

Output

1   Employee [id=1, name=Krishna]
2   Employee [id=2, name=Krishna]
3   Employee [id=3, name=Krishna]
4   Employee [id=4, name=Krishna]



 

You may like

Interview Questions

Collection programs in Java

Array programs in Java

Get the stream from Enumeration in Java

LinkedHashTable implementation in Java

Get the enumeration from a Collection

Get the enumeration from an Iterator in Java

Get a map from enum in Java

Friday, 11 November 2022

Get a map from array in Java

Input: array of values like below.

key1, value1, key2, value2, ……keyN, valueN

 

Output: Get a map out of the array.

key1 -> value1,
key2 -> value2,
………
………
keyN -> valueN

 


MapFromArray.java

package com.sample.app.collections;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class MapFromArray {

	public static Map<Object, Object> toMap(final Object... elements) {
		if (elements == null) {
			return Collections.emptyMap();
		}

		final int noOfElements = elements.length;
		if (noOfElements % 2 != 0) {
			throw new IllegalArgumentException("Number of elements must be an even number to form a map");
		}

		final Map<Object, Object> map = new HashMap<>(noOfElements / 2);
		int i = 0;
		while (i < elements.length - 1) {
			map.put(elements[i++], elements[i++]);
		}
		return map;
	}

	public static void main(String[] args) {
		Object[] empsInfo = { 1, "Krishna", 2, "Ram", 3, "PTR" };
		Map<Object, Object> map = toMap(empsInfo);

		System.out.println(map);

	}

}

 

Output

{1=Krishna, 2=Ram, 3=PTR}

 

 

 

 

 

 

You may like

Interview Questions

Collection programs in Java

Array programs in Java

How to check the object is an iterable or not?

How to check the type or object is a map or not?

Get an iterator from array in Java

Get reverse iterator for the given array in Java

Convert primitive array to wrapper array in Java

Wednesday, 20 July 2022

Java: Map merge method demo

Signature

V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)

 

If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result is null.

 

Example

 

pricesMap.merge("rms", 10.0, (oldValue, newValue) -> oldValue - newValue);

 

Above snippet reduce the price of the product 'rms' by 10 if the key rms exists in the map, else add new entry with the key ‘rms’ and the value ‘10.0’

 

Default implementation of merge method looks like below.

 

V merge(K key, V value,
        BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    Objects.requireNonNull(value);
    V oldValue = get(key);
    V newValue = (oldValue == null) ? value :
               remappingFunction.apply(oldValue, value);
    if(newValue == null) {
        remove(key);
    } else {
        put(key, newValue);
    }
    return newValue;
}

 

Find the below working application.

 


MapMergeDemo.java

 

package com.sample.app.collections;

import java.util.HashMap;
import java.util.Map;

public class MapMergeDemo {

    public static void main(String[] args) {
        Map<String, Double> pricesMap = new HashMap<>();

        pricesMap.put("dlpt", 25000.23);
        pricesMap.put("rms", 500.88);
        pricesMap.put("sgs", 47.89);

        System.out.println(pricesMap);

        System.out.println("\nLet's reduce the price of the product rms by 10 using merge function\n");

        pricesMap.merge("rms", 10.0, (oldValue, newValue) -> oldValue - newValue);

        System.out.println(pricesMap);
        
        System.out.println("\nLet's add new entry using merge function\n");
        
        pricesMap.merge("tshts", 45.3, (oldValue, newValue) -> oldValue - newValue);

        System.out.println(pricesMap);
    }
}

 

Output

{dlpt=25000.23, rms=500.88, sgs=47.89}

Let's reduce the price of the product rms by 10 using merge function

{dlpt=25000.23, rms=490.88, sgs=47.89}

Let's add new entry using merge function

{tshts=45.3, dlpt=25000.23, rms=490.88, sgs=47.89}

 

 

 

 

 

Previous                                                 Next                                                 Home