Friday 12 November 2021

Java: Be cautious while using URL equals method

In this post, I am going to explain why you should be cautious while using the equals method of URL class.

 

How URL equals method works?

As per the Java documentation, equals method documented like below.


 

That means, while checking two urls equality, Java performs a blocking DNS lookup operation to resolve hostname to IP address and then compare the ip addresses.

URL url1 = new URL("https://abc.test.com");
URL url2 = new URL("https://xyz.test.com");

Let's say both of these domains map to same IP address.

https://abc.test.com => 246.103.91.15
https://xyz.test.com => 246.103.91.15


Now when you compare url1 with url2 using equals method, it returns true. But both are different domains, I am expecting it to be false.

 

Apart from this, Since two url comparison using equals method perform a blocking DNS lookup operation to resolve the hostname, it takes lot of time for the comparison. In this case better to use URI (instead of URL) to compare two urls.

 

Let’s see it with an example.

 

URLEquals.java

package com.sample.app.net;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class URLEquals {

	public static List<URL> urls(List<String> urls) throws MalformedURLException {
		List<URL> urlList = new ArrayList<>();

		for (String url : urls) {
			urlList.add(new URL(url));
		}

		return urlList;
	}

	public static List<URI> uris(List<String> urls) throws MalformedURLException, URISyntaxException {
		List<URI> uriList = new ArrayList<>();

		for (String url : urls) {
			uriList.add(new URI(url));
		}

		return uriList;
	}

	public static void main(String args[]) throws URISyntaxException, MalformedURLException {
		boolean state = false;

		List<String> urlStrs = Arrays.asList("https://google.com", "https://youtube.com", "https://facebook.com",
				"https://www.wikipedia.org/", "https://twitter.com/", "https://www.quora.com/",
				"https://www.similarweb.com/", "https://hypestat.com/", "https://in.search.yahoo.com/",
				"https://www.amazon.com/", "https://www.walmart.com/", "https://javarevisited.blogspot.com/",
				"https://javarevisited.blogspot.com/", "https://javahungry.blogspot.com/",
				"https://javabypatel.blogspot.com/", "https://dnb-java.blogspot.com/p/home.html",
				"https://self-learning-java-tutorial.blogspot.com/", "https://javadevelopersguide.blogspot.com/",
				"https://javaknowhow.blogspot.com/", "https://javabasictoadvanced.blogspot.com/",
				"http://biemond.blogspot.com/", "https://javaworld-abhinav.blogspot.com/",
				"http://randomthoughtsonjavaprogramming.blogspot.com/", "https://javadiscover.blogspot.com/",
				"http://marxsoftware.blogspot.com/", "http://craftingjava.blogspot.com/",
				"https://www.java-success.com/", "https://javasolutionsguide.blogspot.com/",
				"https://ebclj.blogspot.com/", "https://www.tabnine.com/", "https://www.linkedin.com/",
				"https://github.com/", "https://www.overops.com/", "https://blog.javapapo.com/",
				"https://www.facebook.com/", "https://www.buggybread.com", "https://www.baeldung.com/",
				"https://www.onlyfullstack.com/", "https://apexapps.oracle.com/", "https://guava.dev/",
				"https://www.java67.com/", "https://blog.feedspot.com/", "https://javapapers.com/",
				"https://www.ideamotive.co/", "https://blogs.sap.com/", "https://www.eclipse.org/",
				"https://www.sololearn.com/", "https://brainly.in/", "https://www.javacodegeeks.com/",
				"https://freecomputerbooks.com/", "https://www.freecodecamp.org/", "https://en.wikipedia.org/");

		List<URL> urls = urls(urlStrs);

		long time1 = System.currentTimeMillis();
		for (URL url1 : urls) {
			for (URL url2 : urls) {

				if (url1.equals(url2)) {
					// System.out.println(url1 + " and " + url2 + " are equal ");
					state = true;// some dummy action
				}

			}
		}

		long time2 = System.currentTimeMillis();

		List<URI> uris = uris(urlStrs);

		long time3 = System.currentTimeMillis();

		for (URI uri1 : uris) {
			for (URI uri2 : uris) {

				if (uri1.equals(uri2)) {
					// System.out.println(uri1 + " and " + uri2 + " are equal ");
					state = true;
				}

			}
		}
		long time4 = System.currentTimeMillis();

		System.out.println("url comparison take " + (time2 - time1) + " milliseconds");
		System.out.println("uri comparison take " + (time4 - time3) + " milliseconds");
	}

}


Output

url comparison take 13478 milliseconds
uri comparison take 2 milliseconds


How URI equals method works?

Two uris are considered to be equals, if

a.   Their schemes must either both be undefined or else be equal without regard to case.

b.   Their fragments must either both be undefined or else be equal.

c.     For two opaque URIs to be considered equal, their scheme-specific parts must be equal.

d.   For two hierarchical URIs to be considered equal, their paths must be equal and their queries must either both be undefined or else be equal.  Their authorities must either both be undefined, or both be registry-based, or both be server-based.  If their authorities are defined and are registry-based, then they must be equal.  If their authorities are defined and are server-based, then their hosts must be equal without regard to case, their port numbers must be equal, and their user-information components must be equal.

 


 

Previous                                                    Next                                                    Home

No comments:

Post a Comment