Tengo una ArrayListcon varios registros y una columna contiene nombres de gas como CO2 CH4 SO2, etc. Ahora quiero recuperar diferentes nombres de gas (únicos) solo sin la repetición de ArrayList. ¿Cómo puede hacerse esto?
Actualizaré las etiquetas. Esta es una pregunta de Java y creo que no está relacionada con jsf y primefaces ...
Mathias Schwarz
Respuestas:
133
Debería utilizar un Set. A Setes una colección que no contiene duplicados.
Si tiene un Listque contiene duplicados, puede obtener entradas únicas como esta:
List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());
NOTA : Este HashSetconstructor identifica duplicados invocando los métodos equals () de los elementos .
El método distinto es una operación intermedia que filtra la secuencia y permite que solo valores distintos (de forma predeterminada, utilizando el método Object :: equals) pasen a la siguiente operación.
Escribí un ejemplo a continuación para su caso,
// Create the list with duplicates.
List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2");
// Create a list with the distinct elements using stream.
List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList());
// Display them to terminal using stream::collect with a build in Collector.
String collectAll = listAll.stream().collect(Collectors.joining(", "));
System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc..
String collectDistinct = listDistinct.stream().collect(Collectors.joining(", "));
System.out.println(collectDistinct); //=> CO2, CH4, SO2
Espero entender su pregunta correctamente: asumiendo que los valores son de tipo String, la forma más eficiente es probablemente convertir a HashSetay iterar sobre él:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
Ahora obtengo los elementos únicos de la lista, pero se está ordenando por sí solo. Pero necesito que los datos no estén ordenados. ¿Cómo se puede hacer?
SDas
6
Esta es una forma sencilla sin recurrir a comparadores personalizados o cosas así:
Set<String> gasNames = new HashSet<String>();
List<YourRecord> records = ...;
for(YourRecord record : records) {
gasNames.add(record.getGasName());
}
// now gasNames is a set of unique gas names, which you could operate on:
List<String> sortedGasses = new ArrayList<String>(gasNames);
Collections.sort(sortedGasses);
Nota: Usar en TreeSetlugar de HashSetdaría una lista de matrices ordenada directamente y la superior Collections.sortpodría omitirse , pero por TreeSetlo demás es menos eficiente, por lo que a menudo es mejor, y rara vez peor, usar HashSetincluso cuando se necesita ordenar.
Cuando estaba haciendo la misma consulta, tuve dificultades para ajustar las soluciones a mi caso, aunque todas las respuestas anteriores tienen buenas perspectivas.
Aquí hay una solución cuando uno tiene que adquirir una lista de objetos únicos, NO cadenas. Digamos que uno tiene una lista de objetos Record. Recordla clase solo tiene propiedades de tipo String, NO propiedad de tipo int. Aquí la implementación se hashCode()vuelve difícil ya que se hashCode()necesita devolver un int.
La siguiente es una Recordclase de muestra .
publicclassRecord{
String employeeName;
String employeeGroup;
Record(String name, String group){
employeeName= name;
employeeGroup = group;
}
public String getEmployeeName(){
return employeeName;
}
public String getEmployeeGroup(){
return employeeGroup;
}
@Overridepublicbooleanequals(Object o){
if(o instanceof Record){
if (((Record) o).employeeGroup.equals(employeeGroup) &&
((Record) o).employeeName.equals(employeeName)){
returntrue;
}
}
returnfalse;
}
@OverridepublicinthashCode(){ //this should return a unique codeint hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 )//again, the multiplier could be anything like 59,79,89, any prime
hash = 89 * hash + Objects.hashCode(this.employeeGroup);
return hash;
}
Como otros sugirieron anteriormente, la clase debe anular tanto equals()el hashCode()método como el para poder usarHashSet .
Ahora, digamos, la lista de registros es allRecord( List<Record> allRecord).
Set<Record> distinctRecords = new HashSet<>();
for(Record rc: allRecord){
distinctRecords.add(rc);
}
Esto solo agregará los distintos registros al Hashset, distintos registros.
Si tiene una matriz de algún tipo de objeto (bean), puede hacer esto:
List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
como dijo Mathias Schwarz anteriormente, pero debe proporcionar a su aBean los métodos hashCode()y equals(Object obj)eso se puede hacer fácilmente en Eclipse mediante un menú dedicado ' Generate hashCode() and equals()' (mientras está en la clase de bean). Set evaluará los métodos anulados para discriminar objetos iguales.
Respuestas:
Debería utilizar un
Set
. ASet
es una colección que no contiene duplicados.Si tiene un
List
que contiene duplicados, puede obtener entradas únicas como esta:List<String> gasList = // create list with duplicates... Set<String> uniqueGas = new HashSet<String>(gasList); System.out.println("Unique gas count: " + uniqueGas.size());
NOTA : Este
HashSet
constructor identifica duplicados invocando los métodos equals () de los elementos .fuente
java: no suitable constructor found for HashSet
. ¿Alguna idea de por qué ocurre esto?Puede utilizar Java 8 Stream API .
El método distinto es una operación intermedia que filtra la secuencia y permite que solo valores distintos (de forma predeterminada, utilizando el método Object :: equals) pasen a la siguiente operación.
Escribí un ejemplo a continuación para su caso,
// Create the list with duplicates. List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2"); // Create a list with the distinct elements using stream. List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList()); // Display them to terminal using stream::collect with a build in Collector. String collectAll = listAll.stream().collect(Collectors.joining(", ")); System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc.. String collectDistinct = listDistinct.stream().collect(Collectors.joining(", ")); System.out.println(collectDistinct); //=> CO2, CH4, SO2
fuente
Espero entender su pregunta correctamente: asumiendo que los valores son de tipo
String
, la forma más eficiente es probablemente convertir aHashSet
ay iterar sobre él:ArrayList<String> values = ... //Your values HashSet<String> uniqueValues = new HashSet<>(values); for (String value : uniqueValues) { ... //Do something }
fuente
ArrayList values = ... // your values Set uniqueValues = new HashSet(values); //now unique
fuente
Esta es una forma sencilla sin recurrir a comparadores personalizados o cosas así:
Set<String> gasNames = new HashSet<String>(); List<YourRecord> records = ...; for(YourRecord record : records) { gasNames.add(record.getGasName()); } // now gasNames is a set of unique gas names, which you could operate on: List<String> sortedGasses = new ArrayList<String>(gasNames); Collections.sort(sortedGasses);
Nota: Usar en
TreeSet
lugar deHashSet
daría una lista de matrices ordenada directamente y la superiorCollections.sort
podría omitirse , pero porTreeSet
lo demás es menos eficiente, por lo que a menudo es mejor, y rara vez peor, usarHashSet
incluso cuando se necesita ordenar.fuente
puede usar esto para hacer una lista única
ArrayList<String> listWithDuplicateValues = new ArrayList<>(); list.add("first"); list.add("first"); list.add("second"); ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());
fuente
Cuando estaba haciendo la misma consulta, tuve dificultades para ajustar las soluciones a mi caso, aunque todas las respuestas anteriores tienen buenas perspectivas.
Aquí hay una solución cuando uno tiene que adquirir una lista de objetos únicos, NO cadenas. Digamos que uno tiene una lista de objetos Record.
Record
la clase solo tiene propiedades de tipoString
, NO propiedad de tipoint
. Aquí la implementación sehashCode()
vuelve difícil ya que sehashCode()
necesita devolver unint
.La siguiente es una
Record
clase de muestra .public class Record{ String employeeName; String employeeGroup; Record(String name, String group){ employeeName= name; employeeGroup = group; } public String getEmployeeName(){ return employeeName; } public String getEmployeeGroup(){ return employeeGroup; } @Override public boolean equals(Object o){ if(o instanceof Record){ if (((Record) o).employeeGroup.equals(employeeGroup) && ((Record) o).employeeName.equals(employeeName)){ return true; } } return false; } @Override public int hashCode() { //this should return a unique code int hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 ) //again, the multiplier could be anything like 59,79,89, any prime hash = 89 * hash + Objects.hashCode(this.employeeGroup); return hash; }
Como otros sugirieron anteriormente, la clase debe anular tanto
equals()
elhashCode()
método como el para poder usarHashSet
.Ahora, digamos, la lista de registros es
allRecord
(List<Record> allRecord
).Set<Record> distinctRecords = new HashSet<>(); for(Record rc: allRecord){ distinctRecords.add(rc); }
Esto solo agregará los distintos registros al Hashset, distintos registros.
Espero que esto ayude.
fuente
Si tiene una matriz de algún tipo de objeto (bean), puede hacer esto:
List<aBean> gasList = createDuplicateGasBeans(); Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
como dijo Mathias Schwarz anteriormente, pero debe proporcionar a su aBean los métodos
hashCode()
yequals(Object obj)
eso se puede hacer fácilmente en Eclipse mediante un menú dedicado 'Generate hashCode() and equals()
' (mientras está en la clase de bean). Set evaluará los métodos anulados para discriminar objetos iguales.fuente
@SuppressWarnings({ "unchecked", "rawtypes" }) public static List getUniqueValues(List input) { return new ArrayList<>(new HashSet<>(input)); }
no olvides implementar tu método de iguales
fuente