Python-like list concept in Java

Ponieważ Java nie zezwala na przekazywanie metod jako parametrów, jakich sztuczek używasz do implementacji Pythona, takich jak rozumienie list w Javie ?

Mam listę (ArrayList) łańcuchów. Muszę przekształcić każdy element za pomocą funkcji, aby uzyskać inną listę. Mam kilka funkcji, które biorą łańcuch jako wejście i zwracają inny łańcuch jako wyjście. Jak zrobić metodę generyczną, która może być podana lista i funkcja jako parametry, tak że mogę uzyskać listę z powrotem z każdym element przetworzony. Nie jest to możliwe w sensie dosłownym, ale jakiej sztuczki powinienem użyć ?

Inną opcją jest napisanie nowej funkcji dla każdej mniejszej funkcji przetwarzania łańcuchów, która po prostu zapętla całą listę, co nie jest takie fajne.

Author: S.Lott, 2009-05-22

6 answers

Zasadniczo tworzysz interfejs funkcji:

public interface Func<In, Out> {
    public Out apply(In in);
}

A następnie przekazać anonimową podklasę do swojej metody.

Twoja metoda może zastosować funkcję do każdego elementu w miejscu:

public static <T> void applyToListInPlace(List<T> list, Func<T, T> f) {
    ListIterator<T> itr = list.listIterator();
    while (itr.hasNext()) {
        T output = f.apply(itr.next());
        itr.set(output);
    }
}
// ...
List<String> myList = ...;
applyToListInPlace(myList, new Func<String, String>() {
    public String apply(String in) {
        return in.toLowerCase();
    }
});

Lub utwórz nowy List (zasadniczo tworzenie mapowania z listy wejściowej do listy wyjściowej):

public static <In, Out> List<Out> map(List<In> in, Func<In, Out> f) {
    List<Out> out = new ArrayList<Out>(in.size());
    for (In inObj : in) {
        out.add(f.apply(inObj));
    }
    return out;
}
// ...
List<String> myList = ...;
List<String> lowerCased = map(myList, new Func<String, String>() {
    public String apply(String in) {
        return in.toLowerCase();
    }
});

Który z nich jest preferowany zależy od Twojego przypadku użycia. Jeśli Twoja lista jest bardzo duża, rozwiązanie na miejscu może być jedynym realnym rozwiązaniem; jeśli chcesz zastosować wiele różne funkcje do tej samej listy oryginalnej aby utworzyć wiele list pochodnych, będziesz potrzebował wersji map.

 33
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-22 18:57:57

W Javie 8 można używać referencji metod:

List<String> list = ...;
list.replaceAll(String::toUpperCase);

Lub, jeśli chcesz utworzyć nową instancję listy:

List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());
 36
Author: yurez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 10:06:39

Biblioteka zbiorów Google ma wiele klas do pracy z kolekcjami i iteratorami na znacznie wyższym poziomie niż zwykłe Java obsługuje, i w sposób funkcjonalny (filtr, Mapa, składanie, itp.). Definiuje Interfejsy funkcji i predykatów oraz metody, które używają ich do przetwarzania zbiorów, tak, że nie trzeba. Posiada również funkcje wygody, które sprawiają, że radzenie sobie z generykami Javy jest mniej uciążliwe.

Używam również Hamcrest * * do filtrowania Kolekcje.

Obie biblioteki można łatwo połączyć z klasami adapterów.


** * * * * * * * * * ]}

 16
Author: Nat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-22 18:31:52
 5
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-22 20:26:30

Buduję ten projekt do pisania list comprehension w Javie, teraz jest proof of concept w https://github.com/farolfo/list-comprehension-in-java

Przykłady

// { x | x E {1,2,3,4} ^ x is even }
// gives {2,4}

Predicate<Integer> even = x -> x % 2 == 0;

List<Integer> evens = new ListComprehension<Integer>()
    .suchThat(x -> {
        x.belongsTo(Arrays.asList(1, 2, 3, 4));
        x.is(even);
    });
// evens = {2,4};

I jeśli chcemy przekształcić wyrażenie wyjściowe w sposób podobny do

// { x * 2 | x E {1,2,3,4} ^ x is even }
// gives {4,8}

List<Integer> duplicated = new ListComprehension<Integer>()
    .giveMeAll((Integer x) -> x * 2)
    .suchThat(x -> {
        x.belongsTo(Arrays.asList(1, 2, 3, 4));
        x.is(even);
    });
// duplicated = {4,8}
 1
Author: farolfo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 18:58:19

Możesz użyć Lambda dla funkcji w następujący sposób:

class Comprehension<T> {
    /**
    *in: List int
    *func: Function to do to each entry
    */
    public List<T> comp(List<T> in, Function<T, T> func) {
        List<T> out = new ArrayList<T>();
        for(T o: in) {
            out.add(func.apply(o));
        }
        return out;
    }
}

Użycie:

List<String> stuff = new ArrayList<String>();
stuff.add("a");
stuff.add("b");
stuff.add("c");
stuff.add("d");
stuff.add("cheese");
List<String> newStuff = new Comprehension<String>().comp(stuff, (a) -> { //The <String> tells the comprehension to return an ArrayList<String>
    a.equals("a")? "1": 
            (a.equals("b")? "2": 
                (a.equals("c")? "3":
                    (a.equals("d")? "4": a
    )))
});

Powróci:

["1", "2", "3", "4", "cheese"]
 0
Author: MrYurihi redstone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-23 12:35:53