2010-08-31 9 views
5

Io uso PriorityQueue per l'ordinamento parziale di alcuni dati. In particolare, questo è il codice:Perché PriorityQueue in Java non può avere initialCapacity 0?

Collection<Data> data = ...; 
PriorityQueue<Data> queue = new PriorityQueue<Data>(data.size(), dataComparator); 
queue.addAll(data); 
// iterate over queue with remove() until we have as much data as we need or until queue is empty 

Sfortunatamente, quando data raccolta è vuota, il codice non riesce, perché PriorityQueue non possono essere passati zero initialCapacity. Quali sono le ragioni alla base di questa decisione di progettazione? Perché non ci può essere un PriorityQueue dimensioni 0?

UPD: So come aggirare questo. Mi piacerebbe sapere perché lo PriorityQueue non include questo max (1, n) codice al suo interno - ci sono dei motivi o è solo una cattiva progettazione dell'API?

+0

Cosa intendi con "il codice non funziona"? Cosa succede esattamente? –

+0

Il costruttore di PriorityQueue genererà un IllegalArgumentException, vedi http://download.oracle.com/javase/6/docs/api/java/util/PriorityQueue.html –

+3

Puoi sempre chiedere a Joshua Bloch (http: //en.wikipedia .org/wiki/Joshua_Bloch). Ha scritto PriorityQueue. –

risposta

9

Perché si vuole utilizzare una coda? Una coda è una struttura dati creata per il caso in cui si ha un "produttore" che accoda gli oggetti e un "consumatore" che li rimuove. Una coda con priorità ordina gli elementi in coda usando una struttura ad albero. È necessario un buffer per consentire ad un produttore di accodare, quindi initialCapacity = 0 non ha senso.

Nel tuo caso sidati mai enqueue nulla, è solo di processo di una collezione che già avete. Perché creare una nuova struttura dati per questo?Si potrebbe utilizzare

for (Data item : Collections.sort(data, dataComparator)) { 
    // ... 
} 

o, dopo il commento di Daniel, utilizzare il Selection Algorithm in modo da poter trarre profitto dalla situazione che è in realtà solo bisogno di un sottoinsieme dei tuoi articoli.

+1

Lo uso per/partial/sort. Potrei avere molti elementi di dati, ma devo selezionare solo i primi 10 o giù di lì, non c'è bisogno di ordinare il resto. – Fixpoint

+1

Devi ordinarli tutti per ottenere la top 10. (+1 per capire il problema) –

+0

Ottenere i primi elementi k di un set può essere fatto facilmente in tempo O (n), mentre l'ordinamento, in generale, richiede (Nel registro n). CLRS comanda su di esso, e wikipedia dà un'ottima referenza sull'argomento: http://en.wikipedia.org/wiki/Selection_algorithm. Per l'elaborazione parallela/distribuita, ci sono le tecniche Map/Reduce: http://pl.postech.ac.kr/~myson/pastwork/dr.html –

1

Se pensate che voglia capacità significa, significa preparare la coda per essere in grado di memorizzare almeno X elementi senza richiedere ulteriori allocazioni di memoria interna. Pertanto, se si prevede che una coda contenga un massimo di 100 elementi, è possibile impostare la capacità su 100 nella funzione di costruzione per prepararla.

Qual è lo scopo di dire a una coda di aspettarsi NESSUN oggetto? Non ha senso consentire 0 in primo luogo, quindi il valore minimo è 1 e il costruttore genera un'eccezione se si passa 0 (o meno).

+1

Il tuo esempio sembra bello ma come dovrebbe lo sviluppatore sapere che saranno 100 elementi quando scrive il codice? Normalmente pensa a "n", e n essere = 0 è una situazione abbastanza normale. – chiccodoro

+1

@chiccodoro: Spesso puoi ricavare un'approssimazione di n da altri dati. E se non puoi, non importa. Questo è solo un suggerimento. Se è troppo piccolo, la coda si ridimensionerà automaticamente. – musiKk

+1

@chiccodoro, 100 elementi è meramente la capacità, non il numero di elementi che verranno memorizzati. Non applicare la tua esperienza a tutti gli altri. Molti problemi hanno un dominio limitato di input, quindi in molti casi uno sviluppatore ha un'idea molto precisa del tipo di capacità di cui potrebbero aver bisogno. Inoltre, n = 0 potrebbe essere una situazione normale, ma è una situazione in cui non utilizzeresti affatto il contenitore, quindi perché fare un gran clamore al riguardo? – mikerobi

0

Perché si desidera creare una raccolta, ma specificare che dovrebbe essere vuota?

Si può solo un'istanza CodaConPriorita con Math.max(1, data.size())

+2

Faccio diverse trasformazioni sulla raccolta iniziale e non voglio scrivere codice separato per il caso quando è vuoto. Meno codice, meglio è. – Fixpoint

1

C'è another constructor è possibile utilizzare per evitare l'IllegalArgumentException.

public PriorityQueue(Collection<? extends E> c) 

La coda di priorità ha una capacità iniziale di 110% della dimensione dell'insieme specificato o 1 se la raccolta è vuota.

Se è necessario il comparatore personalizzato, è possibile effettuare la chiamata come segue (dalla risposta di Jon):

PriorityQueue<Data> queue = new PriorityQueue<Data>(Math.max(data.size(), 1), dataComparator); 

Come altri hanno detto, non ha molto senso avere una coda con nessuna capacità. Dato che devi impostare la capacità minima da qualche parte (di certo non vuoi consentire valori negativi), impostarla su 1 sembra ragionevole.

+2

Suppongo che usi l'altro costruttore perché quello è l'unico modo per passare un comparatore speciale. –

+0

@ Péter Török: Ah, giusto. Questo è un comparatore, non una collezione. Ho letto male. Ho modificato la mia risposta per riflettere questo. –

4

Dal codice sorgente per CodaConPriorita:

/** 
* Priority queue represented as a balanced binary heap: the two children 
* of queue[n] are queue[2*n] and queue[2*n + 1]. The priority queue is 
* ordered by comparator, or by the elements' natural ordering, if 
* comparator is null: For each node n in the heap and each descendant d 
* of n, n <= d. 
* 
* The element with the lowest value is in queue[1], assuming the queue is 
* nonempty. (A one-based array is used in preference to the traditional 
* zero-based array to simplify parent and child calculations.) 
* 
* queue.length must be >= 2, even if size == 0. 
*/ 

Per saperne di più: http://kickjava.com/src/java/util/PriorityQueue.java.htm#ixzz0yBp7ocHR

+0

Descrive come la coda funziona internamente e io chiedo informazioni sulla sua API. – Fixpoint

+3

-1 per un commento di commenti ciechi –

+0

L'API è un'implementazione della struttura dati di PriorityQueue, quindi, in sostanza, @stark è corretto. –

Problemi correlati