Kleines Problem mit Listen und Maps

06/14/2016 15:56 exceble#1
Nabend Dudes,

wie im Titel bereits erwähnt, habe ich ein kleines Problem. Und zwar möchte ich Wörter aus einer Liste ziehen und sie dementsprechend in einer anderen Liste ihrer Wortlänge (Schlüssel als Integer) in einer Map zuweisen.

Nur leider kriege ich nicht das gewünschte Ergebnis. Sobald ich dem Wert eine Liste zuweise, die Liste dann zurrücksetze, wird der Eintrag in der Map ebenfalls zurückgesetzt. Aber das scheint mir unschlüssig, da ich dem Schlüssel die Liste ja bereits zuweise, bevor ich die Liste leere.




Ich hoffe ich drücke mich nicht all zu undeutlich aus, und ihr versteht das Problem. Als Parameter wird eine stumpfe String-List aus Wörtern übergeben. Ich fange grad an Java zu lernen und wollte mich ein wenig mit den Collections auseinandersetzen.

Würde mich über einen kleinen Denkanstoß freuen, da ich mich in das Problem verwickelt habe und gar nicht mehr so ganz weiß, was ich überhaupt schon alles probiert habe. :D

Cheers
06/14/2016 16:33 Belur#2
Ich muss gestehen ich verstehe deinen Code nicht wirklich (kann auch daran liegen, dass ich grade von der Uni komme und mich noch nicht konzentrieren kann ;) ).

Aber sowas wäre mein Vorschlag:
Code:
    public HashMap mapList2(List<String> o) {
        HashMap<Integer, List<String>> m = new HashMap<>();

        for (String element : o) {
            List<String> subList = m.get(element.length());
            if(subList==null){
                m.put(element.length(), new ArrayList<>(Arrays.asList(element)));
            }else{
                m.get(element.length()).add(element);
            }
        }

        System.out.println(m);
        return m;
    }
Du läufst über deine Strings in der übergebenen Liste. Als nächstes lässt du dir das Element aus der Map geben, das als Key die Länge des aktuellen Strings hat.

Falls diese Liste schon existiert, fügst du einfach den String hinzu, ansonsten legst du eine neue Liste mit dem String an.

#Okay hab mir deinen Code nochmal angeguckt:
Wenn du deine Liste in die Map hinzufügst, dann wird keine Kopie der Liste angelegt. Soll heißen, wenn du die Liste danach leerst, dann ist das die gleiche Liste die auch in der Map ist. Diese wird also auch geleert.

Was du willst ist eine "deep copy" der Liste, die du dann hinzufügst:
Code:
    public HashMap mapList(List<String> o) {
        HashMap<Integer, List<String>> m = new HashMap<>();
        ListIterator lt = o.listIterator();

        List<String> lng = new ArrayList<>();

        for (int i = o.get(0).length(); i <= o.get(o.size() - 1).length(); i++) { // i = 3; i <= 10
            lng.clear();
            for (int j = 0; j <= o.size() - 1; j++) {
                if (lt.hasNext()) {
                    //if (lt.next().toString().length() == i) {
                    if (o.get(j).length() == i) {
                        lng.add(o.get(j));
                    } else if (o.get(j).length() >= i) {
                        break;
                    }
                    //}
                }
            }

            System.out.println(lng);
            List<String> w = lng;

            //hier eine deep-copy erstellen.
            List<String> copy = new ArrayList<>();
            for(String s : lng){
                copy.add(s);
            }
            m.put(i, copy);

            System.out.println(m);
            System.out.println(i);
        }
        return m;
    }
Um das nochmal deutlich zu machen:
Code:
        Map<String, List<String>> map = new HashMap<>();
        List<String> list = new ArrayList<>(Arrays.asList("A", "AB", "ABC"));
        map.put("a", list);
        System.out.println(list==map.get("a"));
"list" und die zurückgegeben Liste von "map.get("a")" verweisen beide auf die gleiche Liste. Es wird keine Kopie der Liste in die Map gesteckt oder Ähnliches.
06/14/2016 19:03 exceble#3
Quote:
Originally Posted by Belur View Post
Ich muss gestehen ich verstehe deinen Code nicht wirklich (kann auch daran liegen, dass ich grade von der Uni komme und mich noch nicht konzentrieren kann ;) ).

Aber sowas wäre mein Vorschlag:
Code:
    public HashMap mapList2(List<String> o) {
        HashMap<Integer, List<String>> m = new HashMap<>();

        for (String element : o) {
            List<String> subList = m.get(element.length());
            if(subList==null){
                m.put(element.length(), new ArrayList<>(Arrays.asList(element)));
            }else{
                m.get(element.length()).add(element);
            }
        }

        System.out.println(m);
        return m;
    }
Du läufst über deine Strings in der übergebenen Liste. Als nächstes lässt du dir das Element aus der Map geben, das als Key die Länge des aktuellen Strings hat.

Falls diese Liste schon existiert, fügst du einfach den String hinzu, ansonsten legst du eine neue Liste mit dem String an.

#Okay hab mir deinen Code nochmal angeguckt:
Wenn du deine Liste in die Map hinzufügst, dann wird keine Kopie der Liste angelegt. Soll heißen, wenn du die Liste danach leerst, dann ist das die gleiche Liste die auch in der Map ist. Diese wird also auch geleert.

Was du willst ist eine "deep copy" der Liste, die du dann hinzufügst:
Code:
    public HashMap mapList(List<String> o) {
        HashMap<Integer, List<String>> m = new HashMap<>();
        ListIterator lt = o.listIterator();

        List<String> lng = new ArrayList<>();

        for (int i = o.get(0).length(); i <= o.get(o.size() - 1).length(); i++) { // i = 3; i <= 10
            lng.clear();
            for (int j = 0; j <= o.size() - 1; j++) {
                if (lt.hasNext()) {
                    //if (lt.next().toString().length() == i) {
                    if (o.get(j).length() == i) {
                        lng.add(o.get(j));
                    } else if (o.get(j).length() >= i) {
                        break;
                    }
                    //}
                }
            }

            System.out.println(lng);
            List<String> w = lng;

            //hier eine deep-copy erstellen.
            List<String> copy = new ArrayList<>();
            for(String s : lng){
                copy.add(s);
            }
            m.put(i, copy);

            System.out.println(m);
            System.out.println(i);
        }
        return m;
    }
Um das nochmal deutlich zu machen:
Code:
        Map<String, List<String>> map = new HashMap<>();
        List<String> list = new ArrayList<>(Arrays.asList("A", "AB", "ABC"));
        map.put("a", list);
        System.out.println(list==map.get("a"));
"list" und die zurückgegeben Liste von "map.get("a")" verweisen beide auf die gleiche Liste. Es wird keine Kopie der Liste in die Map gesteckt oder Ähnliches.
Vielen lieben Dank! Das ist genau die Lösung und das wonach ich gesucht habe.

Cheers
06/17/2016 01:02 Achat#4
Fand die Lösung vom Vorposter zu kompliziert.

Code:
Map<Integer, List<String>> map = new HashMap<>();
List<String> target = Arrays.asList("Sansa", "Jaime", "Davos", "Aerys", "Aegon", "Stark", "Jon", "Ser");
for(String s : target) {
	List<String> value = map.getOrDefault(s.length(), new ArrayList<String>());
	map.put(s.length(), value);
	value.add(s);
}
Entry<Integer, List<String>> e;
for(Iterator<Entry<Integer, List<String>>> it = map.entrySet().iterator(); it.hasNext(); ) {
	e = it.next();
	System.out.println(e.getKey() + " " + e.getValue());
}
Viel Spaß mit dem Denkanstoß
06/18/2016 05:26 Devsome#5
#problem solved