1

I'm trying to learn the Java Set interface and have encountered the following code online, I understand the purpose of this code is to convert a Collection<Object> to a TreeSet, but I do not understand how the statement works because the syntax is complex and foreign to me. Could someone walk me through the process step by step?

Set<String> set = people.stream()
                        .map(Person::getName)
                        .collect(Collectors.toCollection(TreeSet::new));

And also, under what kind of circumstances should we prefer the above syntax over the one below?

Set<Integer> s1 = new TreeSet(c1); //where c1 is an instance of Collection interface type
halfer
  • 19,824
  • 17
  • 99
  • 186
Thor
  • 9,638
  • 15
  • 62
  • 137
  • 2
    *"And also, under what kind of circumstances should we prefer the above syntax over the one below?"* They do different things so they aren't interchangeable. The `map` operation is only possible by way of a stream. – Radiodef Mar 10 '16 at 04:36
  • I'm sorry if my question sounds silly, but aren't they both creating an instance of TreeSet? – Thor Mar 10 '16 at 04:38
  • 3
    Yes, but the `map` operation is the whole point of the first snippet. You have e.g. a `List` and want to turn it in to a `Set`. You can't do that with the `TreeSet` constructor. – Radiodef Mar 10 '16 at 04:41
  • 4
    Also, whoa, just noticed something totally unrelated. `new TreeSet(c1)` is really bad. That's called a [raw type](http://stackoverflow.com/q/2770321/2891664) and you can cause heap pollution this way. `c1` doesn't have to be a collection of `Integer`. It can be e.g. a `List` and the code will compile, but you've just put `String` in a `Set` of `Integer` by accident. Very hard to debug because you get a `ClassCastException` somewhere completely different when you try to pull stuff out of `s1`. (The compiler will warn you about this, though.) – Radiodef Mar 10 '16 at 04:47
  • Thank you so much for the detailed explanation! really appreciate it! – Thor Mar 10 '16 at 04:48
  • 2
    Worth reading: [“Enhancements in Java SE 8”](https://docs.oracle.com/javase/8/docs/technotes/guides/language/enhancements.html#javase8) in the [official documentation](https://docs.oracle.com/javase/8/docs/) – Holger Mar 10 '16 at 10:48

2 Answers2

3

people.stream()

Takes a set of people and obtains a stream.

.map(Person::getName)

Takes a stream of people and invokes the getName method on each one, returning a list with all the results. This would be "equivalent" to

for(Person person : people){
    setOfNames.add(person.getName())
}

.collect(Collectors.toCollection(TreeSet::new));

Takes a stream of strings and converts it in a set.


The streams are very useful when you need to apply several transformations. They can also perform very well if you make use of parallel streams, since each transformation (in your case each getName) can be done in parallel instead of sequentially.

Logain
  • 4,259
  • 1
  • 23
  • 32
1

peopele.stream() create a stream of elements .map(Person::getName) takes each object from people collection and calls getName , coverts to string then .collect(Collectors.toCollection(TreeSet::new)) - Collects these String elements and create a TreeSet out of it.

Hope its clear

Raghu K Nair
  • 3,854
  • 1
  • 28
  • 45
  • Thank you very much for your help! Please correct me if Im wrong, but is "people" variable a Collection of instances of "Person" class? – Thor Mar 10 '16 at 04:33