Arrays vergleichen…

Tutorials

Arrays vergleichen…

Ich hatte gerade ein interessantes Problem. Für die Lösung des Problems meiner Artikelservice “Lieber Mister Wong…”, zu finden hier, hier, und hier, musste ich String Arrays vergleichen um festzustellen ob diese identisch sind. Folgendes Problem:

Ein User macht eine Anfrage an die SuchEngine. Diese besteht aus einem oder mehreren Tags, welche in einem StringArray gespeichert werden. Da schon mein Testsystem etwa 100.000 Bookmarks mit 200.000 Bookmark-Tag verknüpfungen handelt könnte es vorkommen, dass sich Anfragen zu einer Tag Kombination doppeln. Insebesondere innerhalb einer User Session dürfte das kein seltenes Phänomen sein. Aufgrund der Tabellenstrukturen bedeutet jedes Tag ein zusätzliches Join eines Subselects, aber ich will ja nicht ausschweifend werden.

Nehmen wir mal an der User sucht Links welche die Tags “online”,”internet” und “blog” besitzen. Je nachdem in welcher Reihenfolge er die Tags setzt kommen dabei folgende Arraykombinationen zustande:

“online”,”internet”,”blog”

“online”,”blog”,”internet”

“blog”,”internet”,”online”

usw…

Theoretisch könnte der Nutzer auch noch sämtliche Groß-/Kleinschreibungvariationen verwenden…

Bevor ich aber dem System jetzt sage es soll für zwei Queries die faktisch identisch sind zwei Temporäre Tabellen anlegen, überprüfe ich doch lieber ob zwei Arrays das gleiche enthalten. Die equals() Methode greift hier nicht, da das mit der Reihenfolge nicht hinhaut. Also folgende Idee:

Wir bilden einen MD5 Hash über das Array und speichern die Hashes zusammen mit dem Array in einer HashMap. Wenn jetzt ein neues Query in Form eines StringArrays reinkommt generieren wir erstmal unseren ArrayHash und überprüfen in der HashMap, ob wir nicht schon eine temporäre Tabelle besitzen, die genau unsere Abfragedaten besitzt.

Da ich nicht beabsichtige hier jemanden mit den Details zu langweilen hier der Sourcecode:

package de.stepload.utils;  

import java.security.MessageDigest;
import java.util.Arrays;  

public class StringArrayHash
{
	public String hashIt(String[] sArray)
	{
		if(sArray.length>0)
		{
			StringBuffer sb = new StringBuffer();  

			Arrays.sort(sArray);  

			for(String s : sArray)
			{
				sb.append(s.toLowerCase().trim());
			}
			return this.createMD5(sb.toString());
		}
		return null;
	}  

    private String createMD5(String sString)
    {
        String sRet = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");  

            md.update( sString.getBytes() );
            byte[] bResult = md.digest();  

            for(int i=0; i                sRet+= hexConvert(bResult[i]);
            }
        } catch(Exception e) {
            	System.out.print(e);
        }  

        return sRet;
    }  

    private String hexConvert(byte b)
    {
        int iValue = (b & 0x7F) + (b< 0 ? 128 : 0);  

        String sRet = (iValue < 16 ? "0" : "");  

        sRet += Integer.toHexString(iValue).toUpperCase();  

        return sRet;
    }
}

Diskussion

3 Kommentare zu “Arrays vergleichen…”

  1. Theoretisch ließe sich das auch erledigen indem man die Strings erstmal alle toLowerCase() setzt, dann sortiert und dann mit der o.g. Array.equals(…) Methode überprüft. Wenn ich aber bereits zu jedem Array einen Hash Wert habe geht das natürlich brauche ich nicht in einer Schleife x-Arrays miteinander zu vergleichen sondern überprüfe einfach ob mein Hash schon da ist.

    Posted by Hathead | April 1, 2008, 13:32
  2. Richtig, der Hash lässt sich auch besser überprüfen und in eine Datenbank packen als ein Vergleich über Java eigene Objekte.

    @Author: Ich bin zwar kein JAVA Programmierer, aber wäre es bei deiner Lösung nicht so, dass folgende Keywords:

    “leben”, “über”, “wolken”

    denselben Hash bilden würden wie:

    “überleben”, “wolken”

    Du müsstest zur Bildung des Hashes noch einen Delimiter einbauen, damit sich solche Wörter nicht überschneiden.

    Hab ich Recht oder etwas übersehen?

    Posted by Ich | April 4, 2008, 01:01
  3. Stimmt :-)

    Posted by Hathead | April 4, 2008, 12:18

Post a comment