Search code examples
javaguavamultimap

Guava: Is it possible not map all entries with Multimaps.index()?


I have a collection of files, some of them do not meet some requirements and some others that are OK. I would like to do, in one iteration, an indexation of those files and the discard of the useless ones. I´d like to do it in one iteration as the number is rather large.

So, I was thinking in using Multimaps.index():

// This is the file list to work on
Collection<File> fileList = FileUtils.listFiles(pathToCtrFiles,
                                                new String[]{"gz"},false);

// Now I want to index the files according to some condition in the file name (a pattern)
ImmutableListMultimap<ENBEquipment, File> mappedFiles = Multimaps.index(fileList, 
new Function<File,ENBEquipment>()
{
    @Override
    public ENBEquipment apply(File input)
    {
        Matcher m = p.matcher(input.getName());
        if (m.matches()){
            return enodebByMacroEnbIdMap.get(m.group(2));
        }

        // I am not interesting in these files. What can I do?
        return null;
    }
});

However, it is not possible to do it as specified in the API:

Throws: NullPointerException - if any of the following cases is true: values is null keyFunction is null An element in values is null keyFunction returns null for any element of values

So my question is, do you have an elegant way to do this, without iterating over the file list twice?

Note: I was thinking in returning a dummy element, but the list returned is immutable (no chance of deleting it).


Solution

  • Just do the indexing manually in that case (you aren't even really indexing if you're leaving some of the values out).

    ImmutableListMultimap.Builder<ENBEquipment, File> builder =
        ImmutableListMultimap.builder();
    for (File file : fileList) {
      Matcher m = p.matcher(file.getName());
      if (m.matches()) {
        builder.put(enodebByMacroEnbIdMap.get(m.group(2)), file);
      }
    }
    ImmutableListMultimap<ENBEquipment, File> mappedFiles = builder.build();
    

    It comes out to fewer lines and is more readable anyway.