# Gathering metadata on files in GitHub

I am a relatively new programmer and am currently working on something with the egit GitHub client library which requires me to iterate over a bunch of values and if a condition is met, add a bunch of stuff to a HashMap then add it to a List.

Example:

List<Map<String, Object>> files = new ArrayList<>();

for (TreeEntry file : fileList) {
if ("blob".equals(file.getType())) {
files.add(new HashMap<String, Object>() {
{
put("sha", file.getSha());
put("path", file.getPath());
put("name", GitHubHelper.getNameFromPath(file.getPath()));
put("size", Objects.toString(file.getSize()));
put("commits", GitHubHelper.getCommits(config, repo, file.getPath()));
}
});
}
}


As far as I understand it, this is almost the same as

Map<String, Object> map = new HashMap<>();
map.put(key, value)


with the only exception that the class is anonymous, which in this case doesn't bother me since I'm adding it to a list and returning it anyway.

Questions:

1. Is the Double-Brace Initialization example different in performance and, in this case in particular, is there any reason why I might choose to do it the regular way? As far as I understand DBI, this should be about the same in terms of performance or am I wrong?

2. Same as Question #1, however, what if in addition to all of this, in this end, I want to return two things as opposed to one. Does that change anything? In my case, I also want to return the repository object these files belong to.

return new HashMap<Repository, List<Map<String, Object>>>() {
{
put(repo, files);
}
};

3. To me, the code looks kind of nice like this. But it kind of feels as if this isn't really the right way. Is there any way I can do this better (tidier/more efficient performance-wise)?

• Are you on Java 8? – h.j.k. Oct 27 '15 at 15:45
• @h.j.k., yes I am. – Sam Oct 27 '15 at 15:46
• Welcome to Code Review! Please update the title with what your code does, not what specific question you have. Also possibly include a bit more code to give context; at the moment this a bit more on-topic for Stack Overflow. That said, otherwise your post looks good. – ferada Oct 27 '15 at 15:55
• There are several Java client libraries for GitHub — which one are you using? – 200_success Oct 28 '15 at 6:57
• @200_success , sorry I haven't included that, I didn't think it was relevant, but it's the Eclipse Egit lib. – Sam Oct 28 '15 at 8:04

# Java 8

Since you are on Java 8, you should consider using its stream-based processing feature to achieve what you need in a more expressive way.

First, you need a method that accepts a TreeEntry and gives you the desired Map object:

private Map<String, Object> extractDetails(TreeEntry file) {
Map<String, Object> map = new HashMap<>();
map.put("sha", file.getSha());
map.put("path", file.getPath());
map.put("name", GitHubHelper.getNameFromPath(file.getPath()));
map.put("size", Objects.toString(file.getSize()));
map.put("commits", GitHubHelper.getCommits(config, repo, file.getPath()));
return map;
}


The idea here is to be able to use this as a method reference, e.g. ThisClass::extractDetails, for map()-ping the filter()-ed elements, before collect()-ing toList():

// Assuming fileList is a Collection implementation
List<Map<String, Object>> files = fileList.stream().filter(f -> "blob".equals(f.getType()))
.map(ThisClass::extractDetails)
.collect(Collectors.toList());


# Double brace initialization

This StackOverflow question shows the pitfalls of using it. In short, yes, there will be a performance impact, and it doesn't end there. Due to the anonymous classes it creates, you may get an unusual number of compiled class files, and not to mention the small but significant gotchas surrounding class equivalence testing (potentially) and final classes.