# min und max Wert in einer Hashtable ?



## Frankster (21. Juli 2005)

Hi!

Bei der folgenden Aufgabe soll man Integerwerte aus einem txt File einlesen und daraus eine Statisik erstellen.

Einlesen ist kein Problem, aber wie kann ich die Werte sortieren bzw den Max und Min Wert heraus lesen ?

Ich hab mir das so vorgestellt:
Man erstellt eine Hashmap.
Der 1. Wert aus dem File wird eingelesen und als Schlüssel der Hashmap verwendet.
Dann wird der nächste Wert eingelesen.
Es wird geschaut ob der Wert schon als Key vorhanden ist, wenn ja, dann erhöhe den Wert um 1.
Wenn nein, dann wird der Wert als neuer Key angelegt und der Inhalt auf 1 gesetzt.

Somit weiss man wie oft jede Zahl vorgekommen ist.

Jetzt  möchte ich aber gerne heraus finden, welcher Wert das Max und Min ist.

Ist die Lösung mit der Hashmap überhaupt gescheit ?

Ich habs als Array auch versucht, aber das ist glaub ich nicht ganz so praktisch.


```
public void auftreten() throws IOException{
        line=source.readLine();
        
        for(int i=0;i<=zaehler;i++){
            while(line != null) {
                tok = new StringTokenizer(line);
                
                while ( tok.hasMoreTokens() ) {
                    String x = tok.nextToken();
                    
                    if ( numbers.containsKey(new Integer(Integer.parseInt(x))) == false ) {
                        numbers.put(new Integer(Integer.parseInt(x)), new Integer(1));
                    }
                    else {
                        Integer z = (Integer)numbers.get(new Integer(Integer.parseInt(x)));
                        String zz = z+"";
                        int wieviel = Integer.parseInt(zz) + 1;
                        numbers.put(new Integer(Integer.parseInt(x)),new Integer(wieviel));
                    }
                }
                line=source.readLine();
            }
        }
        
        for(int i=0;i<=zaehler;i++){
            if ( (numbers.get(new Integer(i))) == null ) {
                numbers.put(new Integer(i),new Integer(0));
            }
            System.out.println(i + " --> " + numbers.get(new Integer(i)));
        }
        System.out.println((numbers.values()));
    }
```


----------



## Frankster (21. Juli 2005)

So ich habs gelöst 

Und zwar so


```
public void max(){
        Enumeration e = numbers.keys();
        while(e.hasMoreElements()){
            Integer alias = (Integer)e.nextElement();
            Integer max = (Integer)numbers.get(alias);
            String maxs = max+"";
            int maximum = Integer.parseInt(maxs);
            
            if (groesste < maximum){
                groesste = maximum;
            }
        }
        
        dest.println();
        dest.println("Welche Zahl kommt am haeufigsten vor: ");
        e = numbers.keys();
        while(e.hasMoreElements()){
            Integer alias = (Integer)e.nextElement();
            Integer max = (Integer)numbers.get(alias);
            String maxs = max+"";
            int maximum = Integer.parseInt(maxs);
            
            if (maximum == groesste) {
                dest.println (alias + " --> " + groesste);    
            }
        }
    }
```
Zuerst hol ich mir jeden Wert aus der Hashtable, und such mir das max.
Anschliessend schau ich zu welchem Key das Maximum gehört, das mach ich mit dem 2. Enumerationdurchlauf, da ich keine Funktion gefunden habe, die mir vom Wert den dazugehörigen Schlüssel liefert :-(

Mfg
Frankster


----------



## Snape (22. Juli 2005)

Moin,
wenn Du nur Integer-Werte hast, würde ich keine Schleife durchlaufen, sondern das keySet() der Hashtable schnappen, daraus eine neue ArrayList erstellen und dann per Collections.sort() sortieren. Danach enthält die ArrayList als ersten und letzten Wert das Maximum und das Minimum.


----------



## Frankster (22. Juli 2005)

Und woher weiss ich dann, welche Wert zu welchem Key gehört ?


----------



## Thomas Darimont (22. Juli 2005)

Hallo!

 Du willst doch die Elemente entsprechend ihrer Häufigkeiten in seltenste und häufigste Elemente einteilen....?

Wenn ja, dann schau mal hier:

```
/**
   * 
   */
  package de.tutorials;
  
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * @author Tom
   * 
   */
  public class NumberStatisticExample {
  
  	/**
  	 * @param args
  	 */
  	public static void main(String[] args) {
  		String str = "1 1 1 3 3 2 3 1 5 5 2 7 7 7 7 7 7 7 7 9";
  		String[] numbers = str.split(" ");
  
  		final String[] maxMin = { "", "" };
  		final int[] maxCntMinCnt = { 0, numbers.length };
  
  		Map<String, Integer> map = new HashMap<String, Integer>() {
  
  			public Integer put(String key, Integer value) {
  				Integer newValue = value;
  
  				if (containsKey(key)) {
 					newValue = get(key) + value;
  				}
  
 				if (newValue > maxCntMinCnt[0]) {
 					maxMin[0] = key;
 					maxCntMinCnt[0] = newValue;
  				}
  				
 		 	if (newValue < maxCntMinCnt[1] || maxMin[1].equals(key)){
 					maxMin[1] = key;
 					maxCntMinCnt[1] = newValue;
  				}
  
 				return super.put(key, newValue);
  			}
  		};
  
  		for (int i = 0; i < numbers.length; i++) {
  			String number = numbers[i];
  			map.put(number, 1);
  		}
  
  		System.out.println(maxMin[0] + " kommt mit " + maxCntMinCnt[0]
  				+ " mal am häufigsten vor.");
  		System.out.println(maxMin[1] + " kommt mit " + maxCntMinCnt[1]
  				+ " mal am seltensten vor.");
  	}
  }
```
 
 Eine (in meinen Augen) noch schickere Variante wäre diese:

```
/**
  * 
  */
 package de.tutorials;
 
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
 /**
  * @author Tom
  * 
  */
 public class NumberStatisticExample {
 
 	/**
 	 * @param args
 	 */
 	public static void main(String[] args) {
 		String str = "1 1 1 3 3 2 3 1 5 5 2 7 7 7 7 7 7 7 7 9";
 		String[] numbers = str.split(" ");
 
 		List<String> numberList = Arrays.asList(numbers);
 		String min, max = min = null;
 		int minCnt = numbers.length, maxCnt = 0;
 		
 		for (String s : new HashSet<String>(numberList)) {
 			int frequency = Collections.frequency(numberList, s);
 			if (frequency > maxCnt) {
 				max = s;
 				maxCnt = frequency;
 			}else if(frequency < minCnt){
 				min = s;
 				minCnt = frequency;
 			}
 		}
 
 		System.out.printf("%s kommt mit %s mal am häufigsten vor.",max,maxCnt);
 		System.out.println();
 		System.out.printf("%s kommt mit %s mal am seltensten vor.",min,minCnt);
 	}
 }
```
 
  Gruß Tom


----------



## Frankster (23. Juli 2005)

Danke 
Muss ich mir genaustens anschaun, weil auf den ersten Blick ist es mir etwas zu hoch *g*

Aber könntest du mir bitte zwei Sachen erklären. Ich hab sie schon bei "Java ist auch eine Insel gesehen", aber nicht verstanden


```
for (String s : new HashSet<String>(numberList))
```

1) Was bedeutet der *:* (Doppelpunkt) ?
2)new HashSet<String> --> was bedeutet es, wenn etwas zwischen spitzen Klammern steht *<String>* ODER
Map*<String, Integer>* map = new HashMap*<String, Integer>*() 

Vielen Dank im voraus
Frankster


----------



## Snape (23. Juli 2005)

Frankster hat gesagt.:
			
		

> 2)new HashSet<String> --> was bedeutet es, wenn etwas zwischen spitzen Klammern steht *<String>* ODER
> Map*<String, Integer>* map = new HashMap*<String, Integer>*()
> 
> Vielen Dank im voraus
> Frankster



Damit wird der Typ spezifiziert, womit man sich beim Auslesen das Casten spart. Normalerweise nimmt HashSet ja Objekte vom Typ Object auf, so dass wenn Strings hineingelegt werden, beim Auslesen auch wieder explizit auf String gecastet werden muss.
Mit der neuen Java5 Syntax ist das nicht mehr nötig, wenn man es wie in Deinem Beispiel oben umsetzt.


----------



## Frankster (23. Juli 2005)

ahsooooo..........

Na damit sollte man aber ziemlich vorsichtig sein oder ?
Wenn man das Programm auf einer älteren Java Version ausführen möchte, wirds nicht gehen


----------



## Snape (23. Juli 2005)

Genau so ist es, deshalb verwende ich bisher auch keinen Java 5 Code.


----------

