¿Cómo puedo formar una lista ordenada de valores extraídos de HashMap?
Pregunta
En realidad, mi problema tiene más matices de lo que sugiere la pregunta, pero quería que el encabezado fuera breve.
tengo un HashMap<String, File>
de File
objetos como valores.las claves son String name
campos que forman parte del File
instancias.Necesito iterar sobre los valores en el HashMap
y devolverlos como un solo String
.
Esto es lo que tengo actualmente:
private String getFiles()
{
Collection<File> fileCollection = files.values();
StringBuilder allFilesString = new StringBuilder();
for(File file : fileCollection) {
allFilesString.append(file.toString());
}
return allFilesString.toString();
}
Esto funciona, pero idealmente quiero el separado. File
valores que se agregarán al StringBuilder
con el fin de int fileID
, que es un campo de la File
clase.
Espero haberlo dejado lo suficientemente claro.
Solución
Algo como esto debería funcionar:
List<File> fileCollection = new ArrayList<File>(files.values());
Collections.sort(fileCollection,
new Comparator<File>()
{
public int compare(File fileA, File fileB)
{
final int retVal;
if(fileA.fileID > fileB.fileID)
{
retVal = 1;
}
else if(fileA.fileID < fileB.fileID)
{
retVal = -1;
}
else
{
retVal = 0;
}
return (retVal);
}
});
Otros consejos
Desafortunadamente no hay forma de obtener datos de un HashMap en un orden reconocible. Debe colocar todos los valores en un TreeSet con un Comparator que use el ID de archivo, o ponerlos en una ArrayList y ordenarlos con Collections.sort, nuevamente con un Comparator que compare de la manera que desee.
El método TreeSet no funciona si hay duplicados, y puede ser excesivo ya que no va a agregar o eliminar elementos del conjunto. El método Collections.sort es una buena solución para casos como este en los que va a tomar todo el HashSet, ordenar los resultados y luego desechar la colección ordenada tan pronto como haya generado el resultado.
Bien, esto es lo que se me ocurrió. Parece resolver el problema, devuelve una Cadena con los objetos de Archivo bien ordenados por su ID de archivo.
public String getFiles()
{
List<File> fileList = new ArrayList<File>(files.values());
Collections.sort(fileList, new Comparator<File>()
{
public int compare(File fileA, File fileB)
{
if(fileA.getFileId() > fileB.getFileId())
{
return 1;
}
else if(fileA.getFileId() < fileB.getFileId())
{
return -1;
}
return 0;
}
});
StringBuilder allFilesString = new StringBuilder();
for(File file : fileList) {
allFilesString.append(file.toString());
}
return allFilesString.toString();
}
Nunca he usado Comparator antes (relativamente nuevo en Java), por lo que agradecería cualquier comentario si he implementado algo incorrectamente.
¿Por qué no recolectarlo en una matriz, ordenarlo y luego concatenarlo?
- MarkusQ
Tendrá que agregar su colección de valores () a una ArrayList y ordenarla usando Collections.sort () con una instancia de Comparator personalizada antes de iterar sobre ella.
Por cierto, tenga en cuenta que no tiene sentido inicializar StringBuffer con el tamaño de la colección, ya que agregará mucho más de 1 carácter por elemento de colección.
Cree una Lista temporal, luego agregue cada par de datos en ella. Ordénelo con Collections.sort () de acuerdo con su comparador personalizado, entonces tendrá la Lista en el orden deseado.
Aquí está el método que está buscando: http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort (java.util.List ,% 20java.util.Comparator)
Creé LinkedHashMap una docena de veces antes de agregarlo al conjunto de colecciones.
Lo que probablemente quiera hacer es crear una colección TreeHashMap.
Crear una segunda colección y agregar cualquier cosa agregada a ambos no es realmente un éxito, y obtienes el rendimiento de ambos (con el costo de un poco de tiempo cuando agregas).
Hacerlo como una nueva colección ayuda a que su código se mantenga limpio y ordenado. La clase de colección debería tener solo unas pocas líneas y debería reemplazar su hashmap existente ...
Si tienes el hábito de envolver siempre tus colecciones, estas cosas simplemente funcionan, nunca lo piensas.
StringBuffer allFilesString = new StringBuffer(fileCollection.size());
A menos que todo su file.toString () sea un carácter en promedio, probablemente esté haciendo que StringBuffer sea demasiado pequeño. (Si no está bien, es mejor que no lo configure y simplifique el código) Puede obtener mejores resultados si lo convierte en un múltiplo del tamaño. Además, StringBuffer está sincronizado, pero StringBuilder no lo está y está allí para ser más eficiente aquí.
Eliminar if
declaración innecesaria.
List<File> fileCollection = new ArrayList<File>(files.values());
Collections.sort(fileCollection,
new Comparator<File>() {
public int compare(File a, File b) {
return (a.fileID - b.fileID);
}
});