J'ai une ArrayList
avec un certain nombre d'enregistrements et une colonne contenant des noms de gaz comme CO2 CH4 SO2, etc. Maintenant, je veux récupérer différents noms de gaz (uniques) uniquement sans interprétation de la ArrayList
. Comment ceci peut être fait?
Vous devriez utiliser un Set .
Un ensemble est un Collection qui ne contient aucun doublon.
Si vous avez une List qui contient des doublons, vous pouvez obtenir les entrées uniques comme ceci:
List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());
NOTE: ce constructeur HashSet identifie les doublons en appelant les méthodes 'equals () des éléments.
Méthode distinct est une opération intermediate qui filtre le flux et permet uniquement aux valeurs de distict (par défaut avec la méthode Object :: equals) de passer à l'opération suivante.
J'ai écrit un exemple ci-dessous pour votre cas,
// 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
J'espère que j'ai bien compris votre question: en supposant que les valeurs sont de type String
, le moyen le plus efficace est probablement de convertir en une HashSet
et d'itérer dessus:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique
Voici un moyen simple sans recourir à des comparateurs personnalisés ou à des choses comme ça:
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);
Remarque: L'utilisation de TreeSet
au lieu de HashSet
donnerait une liste triée directement et une liste supérieure à Collections.sort
pourrait être omise, mais TreeSet
est autrement moins efficace, il est donc souvent préférable, et même pire, d'utiliser HashSet
même lorsque le tri est nécessaire.
Si vous avez un tableau d'un type d'objet (bean), vous pouvez le faire:
List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
comme dit Mathias Schwarz ci-dessus, mais vous devez fournir à votre aBean les méthodes hashCode()
et equals(Object obj)
qui peuvent être effectuées facilement dans Eclipse via le menu dédié 'Generate hashCode() and equals()
' (dans la classe de bean) . Set évaluera les méthodes remplacées par discriminer les objets égaux.
@SuppressWarnings({ "unchecked", "rawtypes" })
public static List getUniqueValues(List input) {
return new ArrayList<>(new HashSet<>(input));
}
n'oubliez pas de mettre en œuvre votre méthode equals
vous pouvez l'utiliser pour créer une liste Unique
ArrayList<String> listWithDuplicateValues = new ArrayList<>();
list.add("first");
list.add("first");
list.add("second");
ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());
Lorsque j'ai posé la même question, j'ai eu du mal à adapter les solutions à mon cas, bien que toutes les réponses précédentes comportent de bonnes idées.
Voici une solution lorsqu'il faut acquérir une liste d'objets uniques, PAS de chaînes. Disons qu’on a une liste d’objets Record. Record
class n'a que des propriétés de type String
, NO des propriétés de type int
. Ici, implémenter hashCode()
devient difficile car hashCode()
doit renvoyer une int
.
Voici un exemple de classe Record
.
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;
}
Comme d'autres l'ont déjà suggéré, la classe doit remplacer les méthodes equals()
et hashCode()
pour pouvoir utiliser HashSet
.
Maintenant, disons, la liste des enregistrements est allRecord
(List<Record> allRecord
).
Set<Record> distinctRecords = new HashSet<>();
for(Record rc: allRecord){
distinctRecords.add(rc);
}
Cela ne fera qu'ajouter les enregistrements distincts au hachage, distinctRecords.
J'espère que cela t'aides.