Created
March 30, 2013 21:00
-
-
Save samskivert/5278311 to your computer and use it in GitHub Desktop.
Scala versions of challenges posed here: http://blog.informatech.cr/2013/03/24/java-streams-preview-vs-net-linq/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Say we have a List of names and we would like to find all those names where "am" occurs: | |
{ | |
// LINQ | |
// string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" }; | |
// List<string> filteredNames = names.Where(c => c.Contains("am")) | |
// .ToList(); | |
// Java Streams | |
// String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; | |
// List<String> filteredNames = stream(names) | |
// .filter(c -> c.contains("am")) | |
// .collect(toList()); | |
val names = Array("Sam", "Pamela", "Dave", "Pascal", "Erik") | |
val filteredNames = names filter(_.contains("am")) toList | |
} | |
// Find all the names in the array "names" where the length of the name is less than or equal to | |
// the index of the element + 1. | |
{ | |
// LINQ | |
// string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" }; | |
// var nameList = names.Where((c, index) => c.Length <= index + 1).ToList(); | |
// Java Streams | |
// String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; | |
// List<String> nameList; | |
// Stream<Integer> indices = intRange(1, names.length).boxed(); | |
// nameList = zip(indices, stream(names), SimpleEntry::new) | |
// .filter(e -> e.getValue().length() <= e.getKey()) | |
// .map(Entry::getValue) | |
// .collect(toList()); | |
val names = Array("Sam", "Pamela", "Dave", "Pascal", "Erik") | |
val nameList = names.zipWithIndex collect { | |
case (c, index) if (c.length <= index+1) => c | |
} toList | |
} | |
// Say we have a list of names and we would like to print “Hello” in front of all the names: | |
{ | |
// LINQ | |
// List<string> nameList1 = new List(){ "Anders", "David", "James", | |
// "Jeff", "Joe", "Erik" }; | |
// nameList1.Select(c => "Hello! " + c).ToList() | |
// .ForEach(c => Console.WriteLine(c)); | |
// Java Streams | |
// List<String> nameList1 = asList("Anders", "David", "James", | |
// "Jeff", "Joe", "Erik"); | |
// nameList1.stream() | |
// .map(c -> "Hello! " + c) | |
// .forEach(System.out::println); | |
// Scala | |
val nameList1 = List("Anders", "David", "James", "Jeff", "Joe", "Erik") | |
nameList1 foreach { n => println(s"Hello! $n") } | |
} | |
// Suppose, we have a dictionary such that each key has a list of values attached to them. Now, | |
// we want to project all the elements in a single collection: | |
{ | |
// LINQ | |
// Dictionary<string, List<string>> map = new Dictionary<string,List<string>>(); | |
// map.Add("UK", new List<string>() {"Bermingham", "Bradford", "Liverpool"}); | |
// map.Add("USA", new List<string>() {"NYC", "New Jersey", "Boston", "Buffalo"}); | |
// var cities = map.SelectMany(c => c.Value).ToList(); | |
// Java Streams | |
// Map<String, List<String>> map = new LinkedHashMap<>(); | |
// map.put("UK", asList("Bermingham","Bradford","Liverpool")); | |
// map.put("USA", asList("NYC","New Jersey","Boston","Buffalo")); | |
// FlatMapper<Entry<String, List<String>>,String> flattener; | |
// flattener = (entry,consumer) -> { entry.getValue().forEach(consumer); }; | |
// List<String> cities = map.entrySet() | |
// .stream() | |
// .flatMap( flattener ) | |
// .collect(toList()); | |
val map = Map("UK" -> List("Bermingham", "Bradford", "Liverpool"), | |
"USA" -> List("NYC", "New Jersey", "Boston", "Buffalo")) | |
val cities = map.values.flatten | |
} | |
// In this case we are interested in evaluating only the first n elements of a collection. For | |
// instance, using a finite list of numbers, obtain the first 4 of them. | |
{ | |
// LINQ | |
// int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; | |
// var first4 = numbers.Take(4).ToList(); | |
// Java Streams | |
// int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13 }; | |
// List<Integer> firstFour; | |
// firstFour = stream(numbers).limit(4) | |
// .boxed() | |
// .collect(toList()); | |
val numbers = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) | |
val first4 = numbers take(4) toList | |
} | |
// In this case we are interested in taking items out of a collection as long as they satisfy a | |
// predicate. Once we find an item that does not satisfy the predicate we stop there. | |
{ | |
// LINQ | |
// string[] moreNames = { "Sam", "Samuel", "Dave", "Pascal", "Erik", "Sid" }; | |
// var sNames = moreNames.TakeWhile(c => c.StartsWith("S")); | |
// Java Streams | |
// String[] names = { "Sam","Samuel","Dave","Pascal","Erik","Sid" }; | |
// List<String> found; | |
// found = stream(names).collect(partitioningBy( c -> c.startsWith("S"))) | |
// .get(true); | |
val moreNames = Array("Sam", "Samuel", "Dave", "Pascal", "Erik", "Sid") | |
val sNames = moreNames takeWhile(_ startsWith "S") toList | |
} | |
// In this case we are interested in skipping items in a collection up to certain arbitrary | |
// number, then we keep the rest of the 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" }; | |
// List<String> skippedList; | |
// skippedList = stream(vipNames).substream(3).collect(toList()); | |
val vipNames = Array("Sam", "Samuel", "Samu", "Remo", "Arnold", "Terry") | |
val skippedList = vipNames drop(3) toList | |
} | |
// In this case we are interested in skipping items out of a collection as long as they satisfy a | |
// predicate. Once we find an item that does not satisfy the predicate we take the rest of the | |
// items from there. | |
{ | |
// LINQ | |
// int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20 }; | |
// var skippedList = numbers.SkipWhile(c => c < 10); | |
// Java | |
// With current streams API I found no way to implement this idiom. | |
val numbers = Seq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20) | |
val skippedList = numbers dropWhile(_ < 10) | |
} | |
// Order the elements of a collection alphabetically: | |
{ | |
// LINQ | |
// string[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" }; | |
// friends = friends.OrderBy(c => c).ToArray(); | |
// Java Streams | |
// String[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" }; | |
// friends = stream(friends).sorted().toArray(String[]::new); | |
val friends = Array("Sam", "Pamela", "Dave", "Anders", "Erik") | |
val sortedFriends = friends.sorted | |
} | |
// Order the elements of a collection strings according to the length of the string: | |
{ | |
// LINQ | |
// string[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" }; | |
// friends = friends.OrderBy(c => c.Length).ToArray(); | |
// Java Streams | |
// String[] friends = { "Sam", "Pamela", "Dave", "Anders", "Erik" }; | |
// friends = stream(friends) | |
// .sorted(comparing((ToIntFunction<String>)String::length)) | |
// .toArray(String[]::new); | |
var friends = Array("Sam", "Pamela", "Dave", "Anders", "Erik") | |
friends = friends.sortBy(_.length) | |
} | |
// Order the elements of a collection of strings according to several sorting criteria: | |
{ | |
// LINQ | |
// string[] fruits = {"grape", "passionfruit", "banana", | |
// "apple", "orange", "raspberry", | |
// "mango", "blueberry" }; | |
// var sortedFruits = fruits.OrderBy(fruit =>fruit.Length) | |
// .ThenBy(fruit => fruit); | |
// Java Streams | |
// String[] fruits = {"grape", "passionfruit", "banana","apple", | |
// "orange", "raspberry","mango", "blueberry" }; | |
// Comparator<String> comparator; | |
// comparator = comparing((Function<String,Integer>)String::length, | |
// Integer::compare) | |
// .thenComparing((Comparator<String>)String::compareTo); | |
// fruits = stream(fruits) .sorted(comparator) | |
// .toArray(String[]::new); | |
val fruits = Array("grape", "passionfruit", "banana", "apple", | |
"orange", "raspberry", "mango", "blueberry") | |
val sortedFruits = fruits sortBy(f => (f.length, f)) | |
} | |
// Group the elements of a collection of strings by their length. | |
{ | |
// LINQ | |
// string[] names = {"Sam", "Samuel", "Samu", "Ravi", "Ratna", "Barsha"}; | |
// var groups = names.GroupBy(c => c.Length); | |
// Java Streams | |
// String[] names = {"Sam", "Samuel", "Samu", "Ravi", "Ratna", "Barsha"}; | |
// Map<Integer,List<String>> groups; | |
// groups = stream(names).collect(groupingBy(String::length)); | |
val names = Array("Sam", "Samuel", "Samu", "Ravi", "Ratna", "Barsha") | |
val groups = names groupBy(_.length) | |
} | |
// Obtain all the distinct elements from a collection. | |
{ | |
// 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 Streams | |
// String[] songIds = {"Song#1", "Song#2", "Song#2", "Song#2", "Song#3", "Song#1"}; | |
// //according to Object.equals | |
// stream(songIds).distinct(); | |
val songIds = Array("Song#1", "Song#2", "Song#2", "Song#2", "Song#3", "Song#1") | |
val uniqueSongIds = songIds.distinct | |
} | |
// Join together two sets of items. | |
{ | |
// LINQ | |
// List<string> friends1 = new List<string>() {"Anders", "David","James", | |
// "Jeff", "Joe", "Erik"}; | |
// List<string> friends2 = new List<string>() { "Erik", "David", "Derik" }; | |
// var allMyFriends = friends1.Union(friends2); | |
// Java Streams | |
// List<String> friends1 = asList("Anders","David","James","Jeff","Joe","Erik"); | |
// List<String> friends2 = asList("Erik","David","Derik"); | |
// Stream<String> allMyFriends = concat(friends1.stream(), | |
// friends2.stream()).distinct(); | |
val friends1 = List("Anders", "David","James", "Jeff", "Joe", "Erik") | |
val friends2 = List("Erik", "David", "Derik") | |
val allMyFriends = Set() ++ friends1 ++ friends2 | |
} | |
// Obtain the first element of a collection. | |
{ | |
// LINQ | |
// string[] otherFriends = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// string firstName = otherFriends.First(); | |
// string firstNameConditional = otherFriends.First(c => c.Length == 5); | |
// Java Streams | |
// String[] otherFriends = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// Optional<String> found = stream(otherFriends).findFirst(); | |
// Optional<String> maybe = stream(otherFriends).filter(c -> c.length() == 5) | |
// .findFirst(); | |
// if(maybe.isPresent()) { | |
// //do something with found data | |
// } | |
val otherFriends = Array("Sam", "Danny", "Jeff", "Erik", "Anders","Derik") | |
val firstName = otherFriends.head | |
val firstNameConditional = otherFriends.find(_.length == 5) | |
} | |
// Generate a range of numbers that are multiples of 11. | |
{ | |
// LINQ | |
// var multiplesOfEleven = Enumerable.Range(1, 100).Where(c => c % 11 == 0); | |
// Java Streams | |
// IntStream multiplesOfEleven = intRange(1,100).filter(n -> n % 11 == 0); | |
val multiplesOfEleven = (1 to 100) filter(_ % 11 == 0) | |
} | |
// Do all elements in a collection satisfy a predicate? | |
{ | |
// LINQ | |
// string[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// bool x = persons.All(c => c.Length == 5); | |
// Java Streams | |
// String[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// boolean x = stream(persons).allMatch(c -> c.length() == 5); | |
val persons = Array("Sam", "Danny", "Jeff", "Erik", "Anders","Derik") | |
val x = persons.forall(_.length == 5) | |
} | |
// Do any elements in a collection satisfy a predicate? | |
{ | |
// LINQ | |
// string[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// bool x = persons.Any(c => c.Length == 5); | |
// Java Streams | |
// String[] persons = {"Sam", "Danny", "Jeff", "Erik", "Anders","Derik"}; | |
// boolean x = stream(persons).anyMatch(c -> c.length() == 5); | |
val persons = Array("Sam", "Danny", "Jeff", "Erik", "Anders","Derik") | |
val x = persons.exists(_.length == 5) | |
} | |
// Combine two collections into a single collection. | |
{ | |
// LINQ | |
// string[] salutations = {"Mr.", "Mrs.", "Ms", "Master"}; | |
// string[] firstNames = {"Samuel", "Jenny", "Joyace", "Sam"}; | |
// string lastName = "McEnzie"; | |
// salutations.Zip(firstNames, (sal, first) => sal + " " + first) | |
// .ToList() | |
// .ForEach(c => Console.WriteLine(c + " " + lastName)); | |
// Java Streams | |
// String[] salutations = {"Mr.", "Mrs.", "Ms", "Master"}; | |
// String[] firstNames = {"Samuel", "Jenny", "Joyace", "Sam"}; | |
// String lastName = "McEnzie"; | |
// zip( | |
// stream(salutations), | |
// stream(firstNames), | |
// (sal,first) -> sal + " " +first) | |
// .forEach(c -> { System.out.println(c + " " + lastName); }); | |
val salutations = Array("Mr.", "Mrs.", "Ms", "Master") | |
val firstNames = Array("Samuel", "Jenny", "Joyace", "Sam") | |
val lastName = "McEnzie" | |
salutations zip(firstNames) map { case (sal, first) => s"$sal $first" } foreach { | |
c => println(s"$c $lastName") } | |
// salutations zip(firstNames) foreach { case (sal, first) => println(s"$sal $first $lastName") } | |
} |
Not highly important, but in the Obtain the first element of a collection, line 258 should read:
// string firstNameConditional = otherFriends.FirstOrDefault(c => c.Length == 5);
To be equivalent to the find method in Scala. This is because First throws an exception if no item matches the predicate, while FirstOrDefault will return a default value (null for reference types).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
With Scala, C# has similar expressiveness where Scala is little more elegant