J'ai la liste des chemins de fichiers:.
List<Path> filePaths; //e.g. [src\test\resources\file\15\54\54_exampleFile.pdf]
54
ci-dessus fait référence à l'ID du fichier
J'obtiens alors un Set
de String
Ids que mon application peut gérer comme suit:
Set<String> acceptedIds = connection.getAcceptedIDs(); //e.g. elements [64, 101, 33]
Comment puis-je utiliser Java 8 lambdas pour filter
sur tous les éléments dans filePaths
qui ne contiennent aucun des identifiants acceptables contenus dans acceptedIds
Ensemble de collection.
En d'autres termes, je voudrais conserver dans filePaths
uniquement les chemins qui ont des identifiants qui sont dans acceptedIds
set. Par exemple, 54 ne figure pas dans la liste ci-dessus et est donc supprimé.
filePaths.stream().filter(...).collect(Collectors.toList());
Le moyen le plus efficace consiste à extraire l'ID du chemin, puis à essayer de le trouver dans l'ensemble, en exécutant chaque filtre en temps constant, c'est-à-dire O(1)
donnant un O(n)
global, où n
est le nombre de chemins:
filePaths.stream()
.filter(p -> acceptedIds.contains(p.getParent().getFileName().toString()))
.collect(Collectors.toList());
Si l'approche inverse est effectuée, où chaque acceptedIds
est recherché dans le chemin (comme dans les autres réponses), chaque filtre est O(m*k)
, où m
est le nombre de acceptedIds
et k
est la longueur moyenne du chemin, donnant un O(n * m * k)
global, qui fonctionnera très mal pour des tailles de collections même modérées.
Vous pourriez écrire:
filePaths.stream()
.filter(p -> acceptedIds.stream().anyMatch(id -> p.toString().contains(id)))
.collect(toList());
Cela filtre chaque chemin de telle sorte qu'au moins un des acceptedIds
soit contenu dans la représentation sous forme de chaîne du chemin. Vous voudrez peut-être implémenter quelque chose de mieux que contains
ici, selon votre cas d'utilisation (correspondant au début du nom de fichier par exemple).
anyMatch
est une opération qui détermine si au moins un élément correspond au prédicat donné.
Notez que cette réponse ne fait aucune hypothèse sur le chemin pour filtrer les éléments. Si vous pouvez dire en toute sécurité que dans chaque chemin, le répertoire parent est nommé avec l'id, vous devez absolument utiliser la réponse @Bohemian, pour des raisons de performances.
Ainsi:
List removeMissing(List l1, List l2) {
List ret = l1.stream()
.filter(o -> l2.contains(o)) //Keep if object o satisfies the condition "l2 contains a reference to this object"
.collect(Collectors.toList());
return ret;
}
Si la structure de votre nom de fichier est constante, j'utiliserais d'abord une expression régulière pour extraire le nombre, puis vérifierait s'il figure parmi les identifiants souhaités.
final Set<String> acceptedIds = ...
// Matches the number of the file, concluded with the underscore
final Pattern extractor = Pattern.compile("\.*(?<number>\d+)_")
filePaths.stream().filter( path -> {
final Matcher m = extractor
.matcher(path.getFileName().toString());
m.find();
return acceptedIds.contains(m.group("number"));
})
...