Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a java lambda expression equivalent of the C# linq let?

Is there a java 8 lambda expression equivalent of the let setting? For instance, how would I write this c# linq expression using Java 8 lambda expressions?

String[] lines = new String[]{"Porky.Pig", "Darth.Vader", "Donald.Duck", "George Lucas"};
(from l in lines      
 let p = l.IndexOf('.')
 where p >= 0
 select new
 {
     FirstName = l.Substring(0, p),
     LastName = l.Substring(p + 1)
 }).Dump();

I want to evaluate l.IndexOf('.') only once. The closest I came up with is:

 String[] lines = new String[]{"Porky.Pig", "Darth.Vader", "Donald.Duck", "George Lucas"};
 Arrays.stream(lines)
       .filter(x -> x.indexOf('.') > 0)
       .map(x -> {
           int p = x.indexOf('.');
           return new Person (x.substring(0, p), x.substring( p + 1));
       });

where:

public class Person {
    public Person(String firstName, String lastName)
    {
    }
}

ok, based on the suggestion in the Shlomi Borovitz's answer I came up with this which makes use of this Pair class

String[] lines = new String[]{"Porky.Pig", "Darth.Vader", "Donald.Duck", "George Lucas"};
Arrays.stream(lines)
      .map(x -> Pair.of(x, x.indexOf('.')))
      .filter(x -> x.getRight() > 0)
      .map(x -> new Person (x.getLeft().substring(0, x.getRight()), x.getLeft().substring( x.getRight()  + 1)));
like image 490
costa Avatar asked Dec 25 '22 08:12

costa


2 Answers

The absence of tuples certainly is a problem. But if we use the declaration of Person in the question and take up @Ulugbek Umirov's suggestion of using String.split, this is a reasonably neat solution:

List<Person> persons = Arrays.stream(lines)
    .map(s -> s.split("\\."))
    .filter(arr -> arr.length > 1)
    .map(arr -> new Person(arr[0], arr[1]))
    .collect(Collectors.toList());

Not being sure what Dump does, I've arbitrarily chosen to collect the Person objects into a List.

like image 103
Maurice Naftalin Avatar answered Dec 28 '22 06:12

Maurice Naftalin


The linq query in C# is converted to "dot syntaxt" (which is regular method calls):
The query:

from l in lines      
let p = l.IndexOf('.')
where p >= 0
select new 
{
    FirstName = l.Substring(0, p), 
    LastName = l.Substring(p + 1)
}

is converted to something like this:

lines.Select(l => new {l, p = l.IndexOf('.') })
     .Where(_ => _.p >= 0)
     .Select(_ => new 
         { 
             FirstName = _.l.SubString(0, _.p), 
             LastName = _.l.SubString(_.p + 1) 
         })

Figure out how to do that in Java.

If there is no equivalent to C#'s anonymous types, tuples are a good idea, where the usage isn't justifying creating another class.

like image 35
Shlomi Borovitz Avatar answered Dec 28 '22 07:12

Shlomi Borovitz