¿Puede alguien explicar PriorityQueue en este ejemplo para mí?

DChalo123:

Estoy tratando de aprender a utilizar un PriorityQueue, ya que nunca he usado una antes. He aquí un ejemplo de uno de cada uso que he encontrado en LeetCode para un problema que encuentra los elementos Top K en una matriz de cadenas

public List<String> topKFrequent(String[] words, int k) {
    Map<String, Integer> count = new HashMap();
    for (String word: words) {
        count.put(word, count.getOrDefault(word, 0) + 1);
    }
    PriorityQueue<String> heap = new PriorityQueue<String>(
            (w1, w2) -> count.get(w1).equals(count.get(w2)) ?
            w2.compareTo(w1) : count.get(w1) - count.get(w2) );

    for (String word: count.keySet()) {
        heap.offer(word);
        if (heap.size() > k) heap.poll();
    }

    List<String> ans = new ArrayList();
    while (!heap.isEmpty()) ans.add(heap.poll());
    Collections.reverse(ans);
    return ans;
}

Más en particular, me gustaría saber lo que está haciendo esta línea:

PriorityQueue<String> heap = new PriorityQueue<String>(
            (w1, w2) -> count.get(w1).equals(count.get(w2)) ?
            w2.compareTo(w1) : count.get(w1) - count.get(w2) );

¿Puede alguien explicar en términos de lame-hombre lo que está sucediendo aquí? ¿Hay alguna manera de volver a escribir la comparater como regular "if"?

Gracias por cualquier ayuda.

ricky3350:

La expresión que tiene en el constructor es una expresión lambda . Debido a que Comparatores una interfaz funcional, es decir, que es una interfaz con un único método abstracto, una expresión lambda puede ser utilizado como abreviatura para la creación de una clase anónima.

En su ejemplo,

new PriorityQueue<String>((w1, w2) -> count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2));

es funcionalmente equivalente a

new PriorityQueue<String>(new Comparator<String>() {
    public int compare(String w1, String w2) {
        return count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2);
    }
});

Este también sería el mismo que hacer una clase separada que implementos Comparator<String>, y que pasa a una instancia de esa clase que el parámetro al PriorityQueue.

En cuanto a la escritura Comparatorcomo una sentencia if, la respuesta corta es no. El comparador tiene que ser una instancia de Comparator<String>. Sin embargo, tal vez una versión más comprensible de la misma comparador es el siguiente:

new PriorityQueue<String>((w1, w2) -> {
    if (count.get(w1).equals(count.get(w2))) { // If the counts of w1 and w2 are the same,
        return w2.compareTo(w1); // Then return the reverse lexicographical ordering of w1 and w2 (e.g. "Zebra" comes before "Apple")
    } else if (count.get(w1) < count.get(w2)) {
        return -1; // w1 comes before w2
    } else {
        return 1; // w1 comes after w2
    }
});

Nota: "ordenamiento lexicográfico" es esencialmente orden alfabético, pero en base a los códigos ASCII. Para más información, verString#compareTo(String)

¡Espero que esto ayude!

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=225381&siteId=1
Recomendado
Clasificación