Basic Usage
The Person
object we will use in this article
public class Person{
int age;
String name;
boolean isFemail;
public Person(String name, int age, boolean isFemale){
this.name = name;
this.age = age;
this.isFemail = isFemale;
}
public Person(int age, boolean isFemale){
this.age = age;
this.isFemail = isFemale;
}
public boolean isFemale(){
return this.isFemail;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
@Override
public String toString(){
return "name:" + name + " age: " + age + " isFemale: " + isFemale();
}
@Override
public boolean equals(Object obj){
if( obj == this)return true;
if(!(obj instanceof Person))return false;
Person p = (Person)obj;
return p.getName().equals(this.name);
}
@Override
public int hashCode(){
return name.hashCode();
}
}
1. Remove Duplicate
List<Person> distinct = persons.stream().distinct().collect(Collectors.toList());
2. Sum with reduce()
int sum = persons.stream().map(e -> e.getAge()).reduce(0,(a,b) -> a + b);
use map()
to get the age value and then use reduce()
to add next numbers together.
3. Count
long count = persons.stream().count();
4. Average
double average = persons.stream().mapToInt(e -> e.getAge()).average().getAsDouble();
You also can use mapToLong
, mapToDouble
. mapToInt
, mapToLong
and mapToDouble
are the “Boxing” version of map
, it is same as map.
5. Pull the Attributes of object from list by map()
and flatMap()
map()
and flatMap()
methods can pull data or Attribute on each element in the list. The Difference between 2 is:
map()
1 value in -> 1 value out
flatMap()
1 value in -> 0..n values out
List<String> names = persons.stream().map(e -> e.getName()).collect(Collectors.toList());
Pull all the names of person from the list.
6. Update object from list by map()
and flatMap()
by multiple line lamba expression
List<Person> result = persons.stream().map(e -> {
Person p = new Person(e.getName(), e.getAge(), e.isFemale());
p.setAge(p.getAge() + 10);
return p;
}).collect(Collectors.toList());
This code will add 10 on each person’s age and then return new list
7. sort
List<Person> sorted = persons.stream().sorted(Comparator.comparingInt(e -> e.getAge()))
.collect(Collectors.toList());
sort by age small to big, you also can use customized sort compareator
Comparator<Person> reverseComparator = new Comparator<Person>() {
@Override
public int compare(Person e1, Person e2) {
return e1.getAge() > e2.getAge() ? -1 : 1;
}
};
List<Person> sorted = persons.stream().sorted(reverseComparator).collect(Collectors.toList());
reverse the sort, but you can use that method to apply on any sort
8. Find
- Find One Element
Optional<Person> femalePerson = persons.stream().filter(e -> e.isFemale()).findFirst();
Optional<Person> femalePerson = persons.stream().filter(e -> e.isFemale()).findAny();
if(femalePerson.isPresent()){
System.out.println(femalePerson.get());
}
findFirst()
will return first found female person in the list if you are NOT use “parallel()”, findAny()
return found female person but non-deterministic
- Find Multiple Elements (by
filter
)
** I would like to call filter
as one of find functions, it could return 1 or n elements from list.
List<Person> femalePersons = persons.stream()
.filter(e -> e.isFemale()).collect(Collectors.toList());
for(Person female: femalePersons){
System.out.println(female);
}
- Find Multiple Elements by
Predicate
- separate the logic apart
Predicate<Person> ageGreaterThan10 = new Predicate<Person>() {
@Override
public boolean test(Person p) {
return p.getAge() > 10;
}
};
List<Person> result = persons.stream()
.filter(ageGreaterThan10)
.collect(Collectors.toList());
9. match
- AnyMatch
boolean existFemale = persons.stream().anyMatch(e -> e.isFemale() );
This return true if any “person” in the list return isFemale true.
- All Match
boolean allFemale = persons.stream().allMatch(e -> e.isFemale());
This will return true if and only if all person in the list is female.
- None Match
boolean noFemale = persons.stream().noneMatch(e -> e.isFemale());
This will return true if and only if none of person in list is female.
10 Limit and Skip
List<Person> limit = persons.stream().limit(1).collect(Collectors.toList());
This will get the first element from the list, you can change the number in limit()
to get more
List<Person> skip = persons.stream().skip(persons.size() - 1).collect(Collectors.toList());
This will get you the last element of the list
11 use filter()
to parse String
Suppose we have String like this:
String s = "number1 1 number2 2 number3 3";
we want to parse out all the number: 1, 2 and 3, we can use following way:
List<Integer> l = Arrays.stream(s.split(" "))
.filter(e -> e.matches("\\d+"))
.mapToInt(i -> Integer.valueOf(i))
.boxed().collect(Collectors.toList());
you need to use boxed()
because mapToInt()
return is “int” type, you need to boxed to convert to Integer
12 use map
to apply function on each element
You can use map
method to apply a function (usually lambda) on each element and then return new value (MUST return)
List<Integer> result = input.stream().parallel().map( e ->{
System.out.println(e + " thread name: " + Thread.currentThread().getName());
return e * 10;
}).collect(Collectors.toList());
result.forEach(System.out::println);
This shows for each integer in the list(input), multiply 10 and then add into another list(result)
13 Showcase 1: scan files in directory and proceed
Following code show provide the list of files in a directory as stream:
private Stream<File> scanDirectory(Path directory){
File[] files = directory.toFile().listFiles(this::fileFilter);
if(files == null){
throw new RuntimeException("can not list files for " + directory);
}
return Arrays.stream(files);
}
private boolean fileFilter(File file){
return file.isFile() &&
filePattern.matcher(file.getName()).find();
}
then process
method take stream and work on the file:
public void process(){
try {
Path path = getWatchPath();
scanDirectory(path).map(File::getAbsolutePath)
.filter(this::findNonTextFile)
.findFirst()
.ifPresent(filePath -> processFile(filePath, fileHandler.apply(filePath)));
} catch (IOException e) {
// e.printStackTrace();
log.error("IOException {}", e);
}
}
scanDirectory(path)
return a Stream
object of File
, then use map
to get absolute path of each file then use ifPresent
to proceed the file.