Java Streams vs C# LINQ vs Java6 - updated examples
2014-05-17
Java 8 is published. This post is a rewrite of my previous one with updated examples. I added a third example to each challenge demonstrating how my functional-utils library could be used with lambdas.
Challenge 1: Filtering
LINQ :
string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
<string> filteredNames = names.Where(c => c.Contains("am"))
List.ToList();
Java :
String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
// Java Streams
List<String> filtered8 = stream(names).filter(c -> c.contains("am")).collect(toList());
// Java 6 with functional-utils
List<String> filtered6 = newList(filter(String_.contains.apply(_, "am"), names));
// Java 8 with functional-utils
List<String> filtered_ = newList(filter(c -> c.contains("am"), names));
Challenge 2: Indexed Filtering
LINQ :
string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();
Java :
static boolean pred(int index, String name) {
return name.length() <= index + 1;
}
// ...
String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
// Java Streams
= IntStream.range(1, names.length).iterator();
OfInt indices List<String> nameList8 = stream(names).map(c -> Pair.of(indices.next(), c))
.filter(c -> c.getValue().length() <= c.getKey())
.map(Pair::getValue)
.collect(toList());
// Java 6 with functional-utils
List<String> nameList6 = newList(map(Tuple2_.<String>_2(),
filter(pred, zipWithIndex(names))));
// Java 8 with functional-utils
List<String> nameList_ = newList(map(Tuple2::get_2,
filter(t2 -> t2._2.length() <= t2._1+1,
zipWithIndex(names))));
Challenge 3: Selecting/Mapping
LINQ :
<string> nameList1 = new List(){ "Anders", "David", "James",
List"Jeff", "Joe", "Erik" };
.Select(c => "Hello! " + c).ToList()
nameList1.ForEach(c => Console.WriteLine(c));
Java :
List<String> nameList = Arrays.asList("Anders", "David", "James","Jeff", "Joe", "Erik");
// Java Streams
.stream().map(c -> "Hello! " + c).forEach(System.out::println);
nameList
// Java 6 with functional-utils
foreach(PrintStream_.println8.ap(System.out),
map(String_.concat.ap("Hello! "), nameList));
// Java 8 with functional-utils
foreach(System.out::println, map(c -> "Hello! " + c, nameList));
Challenge 4: Selecting Many/Flattening
LINQ :
<string, List<string>> map = new Dictionary<string,List<string>>();
Dictionary.Add("UK", new List<string>() {"Bermingham", "Bradford", "Liverpool"});
map.Add("USA", new List<string>() {"NYC", "New Jersey", "Boston", "Buffalo"});
mapvar cities = map.SelectMany(c => c.Value).ToList();
Java :
Map<String, List<String>> map = new HashMap<>();
.put("UK", Arrays.asList("Bermingham","Bradford","Liverpool"));
map.put("USA", Arrays.asList("NYC","New Jersey","Boston","Buffalo"));
map
// Java Streams
List<String> cities8 = map.entrySet().stream()
.map(Map.Entry::getValue)
.flatMap(List::stream)
.collect(toList());
// Java 6 with functional-utils
List<String> cities6 = newList(flatMap(Map_.Entry_.getValue(), map.entrySet()));
// Java 8 with functional-utils
List<String> cities_ = newList(flatMap(Map.Entry::getValue, map.entrySet()));
Challenge 5: Taking an Arbitrary Number of Items
LINQ :
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
var first4 = numbers.Take(4).ToList();
Java :
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13 };
// Java Streams
List<Integer> firstFour8 = stream(numbers).limit(4).boxed().collect(toList());
// Java 6 with functional-utils
List<Integer> firstFour6 = newList(take(4, newArray(numbers)));
// Java 8 with functional-utils
List<Integer> firstFour_ = newList(take(4, newArray(numbers)));
Challenge 6: Taking Items Based on Predicate
LINQ :
string[] moreNames = { "Sam", "Samuel", "Dave", "Pascal", "Erik", "Sid" };
var sNames = moreNames.TakeWhile(c => c.StartsWith("S"));
Java :
String[] names = { "Sam","Samuel","Dave","Pascal","Erik","Sid" };
// Java Streams
// Still cannot do this, since takeWhile is not in the API.
// Java 6 with functional-utils
List<String> found6 = newList(takeWhile(String_.startsWith.apply(_, "S"), names));
// Java 8 with functional-utils
List<String> found_ = newList(takeWhile(c -> c.startsWith("S"), names));
Challenge 7: Skipping an Arbitrary Number of Items
LINQ :
string[] vipNames = { "Sam", "Samuel", "Samu", "Remo", "Arnold","Terry" };
var skippedList = vipNames.Skip(3).ToList();//Leaving the first 3.
Java :
String[] vipNames = { "Sam", "Samuel", "Samu", "Remo", "Arnold","Terry" };
// Java Streams
List<String> skippedList8 = stream(vipNames).skip(3).collect(toList());
// Java 6 with functional-utils
List<String> skippedList6 = newList(drop(3, vipNames));
// Java 8 with functional-utils
List<String> skippedList_ = newList(drop(3, vipNames));
Challenge 8: Skipping Items Based on Predicate
LINQ :
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20 };
var skippedList = numbers.SkipWhile(c => c < 10);
Java :
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20 };
// Java Streams
// Still cannot do this, since skipWhile is not in the API.
// Java 6 with functional-utils
List<Integer> skippedList6 = newList(dropWhile(lessThan(10), newArray(numbers)));
// Java 8 with functional-utils
List<Integer> skippedList_ = newList(dropWhile(c -> c < 10, newArray(numbers)));
Challenge 9: Ordering/Sorting Elements
LINQ :
string[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" };
= friends.OrderBy(c => c).ToArray(); friends
Java :
String[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" };
// Java Streams
String[] friends8 = stream(friends).sorted().toArray(String[]::new);
// Java 6 with functional-utils
String[] friends6 = newArray(String.class, sort(friends));
// Java 8 with functional-utils
String[] friends_ = newArray(String.class, sort(friends));
Challenge 10: Ordering/Sorting Elements by Specific Criterium
LINQ :
string[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" };
= friends.OrderBy(c => c.Length).ToArray(); friends
Java :
String[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" };
// Java Streams
String[] friends8 = stream(friends).sorted(comparing(String::length))
.toArray(String[]::new);
// Java 6 with functional-utils
String[] friends6 = newArray(String.class, sort(by(String_.length), friends));
// Java 8 with functional-utils
String[] friends_ = newArray(String.class, sort(by(String::length), friends));
Challenge 11: Ordering/Sorting Elements by Multiple Criteria
LINQ :
string[] fruits = {"grape", "passionfruit", "banana",
"apple", "orange", "raspberry",
"mango", "blueberry" };
//Sort the strings first by their length and then alphabetically.
//preserving the first order.
var sortedFruits = fruits.OrderBy(fruit =>fruit.Length)
.ThenBy(fruit => fruit);
Java :
String[] fruits = {"grape", "passionfruit", "banana","apple", "orange", "raspberry" };
// Java Streams
String[] fruits8 = stream(fruits).sorted(comparing(String::length)
.thenComparing(naturalOrder()))
.toArray(String[]::new);
// Java 6 with functional-utils
String[] fruits6 = newArray(String.class,
sort(by(String_.length).then(byNatural()), fruits));
// Java 8 with functional-utils
String[] fruits_ = newArray(String.class,
sort(by(String::length).then(byNatural()), fruits));
Challenge 12: Grouping by a Criterium
LINQ :
string[] names = {"Sam", "Samuel", "Samu", "Ravi", "Ratna", "Barsha"};
var groups = names.GroupBy(c => c.Length);
Java :
String[] names = {"Sam", "Samuel", "Samu", "Ravi", "Ratna", "Barsha"};
// Java Streams
Map<Integer,List<String>> groups8 = stream(names).collect(groupingBy(String::length));
// Java 6 with functional-utils
Map<Integer, List<String>> groups6 = groupBy(String_.length, names);
// Java 8 with functional-utils
Map<Integer, List<String>> groups_ = groupBy(String::length, names);
Challenge 13: Filter Distinct Elements
LINQ :
string[] songIds = {"Song#1", "Song#2", "Song#2", "Song#2", "Song#3", "Song#1"};
//This will work as strings implement IComparable
var uniqueSongIds = songIds.Distinct();
Java :
String[] songIds = {"Song#1", "Song#2", "Song#2", "Song#2", "Song#3", "Song#1"};
// Java Streams
List<String> distinct8 = stream(songIds).distinct().collect(toList());
// Java 6 with functional-utils
List<String> distinct6 = newList(distinct(songIds));
// Java 8 with functional-utils
List<String> distinct_ = newList(distinct(songIds));
Challenge 14: Union of Two Sets
LINQ :
<string> friends1 = new List<string>() {"Anders", "David","James",
List"Jeff", "Joe", "Erik"};
<string> friends2 = new List<string>() { "Erik", "David", "Derik" };
Listvar allMyFriends = friends1.Union(friends2);
Java :
List<String> friends1 = Arrays.asList("Anders","David","James","Jeff","Joe","Erik");
List<String> friends2 = Arrays.asList("Erik","David","Derik");
// Java Streams
Set<String> allMyFriends8 = Stream.concat(friends1.stream(), friends2.stream())
.collect(toSet());
// Java 6 with functional-utils
Set<String> allMyFriends6 = union(newSet(friends1), newSet(friends2));
// Java 8 with functional-utils
Set<String> allMyFriends_ = union(newSet(friends1), newSet(friends2));
Challenge 15: First Element
LINQ :
string[] otherFriends = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
string firstName = otherFriends.First();
string firstNameConditional = otherFriends.First(c => c.Length == 5);
Java :
String[] otherFriends = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
// Java Streams
<String> firstName8 = stream(otherFriends).findFirst();
Optional<String> firstNameCondl8 = stream(otherFriends).filter(c -> c.length() == 5)
Optional.findFirst();
// Java 6 with functional-utils
Option<String> firstName6 = headOption(otherFriends);
Option<String> firstNameCondl6 = find(String_.length.andThen(equalTo(5)), otherFriends);
// Java 8 with functional-utils
Option<String> firstName_ = headOption(otherFriends);
Option<String> firstNameCond_ = find(c -> c.length() == 5, otherFriends);
Challenge 16: Generate a Range of Numbers
LINQ :
var multiplesOfEleven = Enumerable.Range(1, 100).Where(c => c % 11 == 0);
Java :
// Java Streams
List<Integer> multiplesOfEleven8 = IntStream.rangeClosed(1,100)
.filter(n -> n % 11 == 0)
.boxed()
.collect(toList());
// Java 6 with functional-utils
List<Integer> multiplesOfEleven6 = newList(filter(mod(11).andThen(equalTo(0)),
range(1, 100)));
// Java 8 with functional-utils
List<Integer> multiplesOfEleven_ = newList(filter(c -> c % 11 == 0, range(1, 100)));
Challenge 17: All
LINQ :
string[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
bool x = persons.All(c => c.Length == 5);
Java :
String[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
// Java Streams
boolean x8 = stream(persons).allMatch(c -> c.length() == 5);
// Java 6 with functional-utils
boolean x6 = forall(String_.length.andThen(equalTo(5)), persons);
// Java 8 with functional-utils
boolean x_ = forall(c -> c.length() == 5, persons);
Challenge 18: Any
LINQ :
string[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
bool x = persons.Any(c => c.Length == 5);
Java :
String[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"};
// Java Streams
boolean x8 = stream(persons).anyMatch(c -> c.length() == 5);
// Java 6 with functional-utils
boolean x6 = exists(String_.length.andThen(equalTo(5)), persons);
// Java 8 with functional-utils
boolean x_ = exists(c -> c.length() == 5, persons);
Challenge 19: Zip
LINQ :
string[] salutations = {"Mr.", "Mrs.", "Ms", "Master"};
string[] firstNames = {"Samuel", "Jenny", "Joyace", "Sam"};
string lastName = "McEnzie";
.Zip(firstNames, (sal, first) => sal + " " + first)
salutations.ToList()
.ForEach(c => Console.WriteLine(c + " " + lastName));
Java :
String[] salutations = { "Mr.", "Mrs.", "Ms", "Master" };
String[] firstNames = { "Samuel", "Jenny", "Joyace", "Sam" };
String lastName = "McEnzie";
// Java Streams
Iterator<String> sal = stream(salutations).iterator();
stream(firstNames).map(c -> sal.next() + " " + c + " " + lastName)
.forEach(System.out::println);
// Java 6 with functional-utils
foreach(PrintStream_.println8.ap(System.out),
map(Tuple_.<String>asList16().andThen(Functional_.mkString1.ap(" ")),
zip(salutations, firstNames, repeat(lastName))));
// Java 8 with functional-utils
foreach(System.out::println, map(c -> c._1 + " " + c._2 + " " + c._3,
zip(salutations, firstNames, repeat(lastName))));