Summarize what you learned about C # lambdas. The case of Java 8 is also described.
The following example describes the history of lambda.
Example: Extract data by the length of a character string from an array of String.
No lambda
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values);
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values)
{
var result = new List<string>();
foreach (var val in values)
{
if (val.Length > 2)
{
result.Add(val);
}
}
return result.ToArray();
}
Execution result
ccc,dddd,eeeee
In the above example, the ones with a size larger than 2 are extracted, but when you want to extract the cases with a size of 3 or less, it cannot be handled. You can take 2 of "if (val.Length> 2)" as an argument, but you cannot change the equal sign such as above, below, and so on.
delegate
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values, Check1);
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values, LengthCheck check)
{
var result = new List<string>();
foreach (var val in values)
{
if (check(val))
{
result.Add(val);
}
}
return result.ToArray();
}
delegate bool LengthCheck(string value);
bool Check1(String value)
{
return value.Length > 2;
}
Expressions can now be passed by using delegate. Therefore, if you want to extract 3 or less, create a Check2 method for the following and pass it.
delegate2
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values, Check2);
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values, LengthCheck check)
{
var result = new List<string>();
foreach (var val in values)
{
if (check(val))
{
result.Add(val);
}
}
return result.ToArray();
}
delegate bool LengthCheck(string value);
bool Check1(String value)
{
return value.Length > 2;
}
bool Check2(String value)
{
return value.Length <= 3;
}
In the above example, we need to create a method and think about the method name. Also, since the actual declaration is different from the calling "GetData (values, Check2)", there is a problem that it is difficult to understand what is being done.
Anonymous method
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values,
delegate(string s) { return s.Length <= 3; }) ;
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values, LengthCheck check)
{
var result = new List<string>();
foreach (var val in values)
{
if (check(val))
{
result.Add(val);
}
}
return result.ToArray();
}
delegate bool LengthCheck(string value);
Anonymous methods have solved that problem. Anonymous methods were introduced in .NET 2.0.
Generics were introduced in .NET 2.0, and as a result, using bool Predicate \
Predicate
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values,
delegate(string s) { return s.Length <= 3; }) ;
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values, Predicate<string> check)
{
var result = new List<string>();
foreach (var val in values)
{
if (check(val))
{
result.Add(val);
}
}
return result.ToArray();
}
The lambda operator "=>] was written as "delegate (string s) {return s.Length <= 3;}" in the anonymous method. If you write in, it will be as follows.
Lambda expression
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = GetData(values, s => s.Length <= 3) ;
Console.WriteLine(string.Join(",", result));
}
private string[] GetData(string[] values, Predicate<string> check)
{
var result = new List<string>();
foreach (var val in values)
{
if (check(val))
{
result.Add(val);
}
}
return result.ToArray();
}
Lambda expressions were introduced in .NET 3.0. The lambda operator is read as "Goes to". The left side is the parameter and the right side is the expression or statement
For this sample, the following code gives the same result
bonus
private void button2_Click(object sender, EventArgs e)
{
var values = new string[] { "a", "bb", "ccc", "dddd", "eeeee" };
var result = values.Where(s => s.Length <= 3);
Console.WriteLine(string.Join(",", result));
}
I used to write "delegate" and "string" like "delegate (string s) {return s.Length <= 3;})", but it is no longer necessary.
Because the second parameter of "GetData (values, s => s.Length <= 3)" is "private string [] GetData (string [] values, Predicate
It should be noted that writing for the following does not cause an error.
It is OK to specify the type
GetData(values, (string s) => s.Length <= 3) ;
() Is required when there are 0 parameters.
0 parameters
() => hoge
() Is not required when there is one parameter. Even if there is, it is OK.
1 parameter
s => hoge
If there are multiple parameters, enclose them in () and separate them with commas.
Multiple parameters
(a,b) => hoge
no return required
GetData(values, s => s.Length <= 3) ;
With return
GetData(values, s => { return s.Length <= 3; }) ;
Func has a return value, Action has no return value.
In Func \ <T, T, Result>, the end of the angle bracket is the return type. The maximum number of parameters is 16. Now that we have Func, we don't use Predicate anymore.
3-1.Action
A sample that outputs start and end logs for heavy methods and runs them asynchronously.
Action sample
private void button2_Click(object sender, EventArgs e)
{
Wrap(Execute);
}
private void Execute()
{
Console.WriteLine("Heavy processing execution");
System.Threading.Thread.Sleep(5000);
}
private async void Wrap(Action action)
{
Console.WriteLine("START");
await Task.Run(() => action());
Console.WriteLine("END");
}
C#
private void button2_Click(object sender, EventArgs e)
{
int[] values = new int[] { 2, 5, 3, 1, 8, 4, 2, 6 };
//Extract values of 5 and above in ascending order
var result = values.Where(v => v >= 5).OrderBy(v => v);
Console.WriteLine(string.Join(",", result));
}
Java
import java.util.Arrays;
import java.util.stream.IntStream;
public class Sample {
public static void main(String[] args) {
int[] values = new int[] { 2, 5, 3, 1, 8, 4, 2, 6 };
//Extract values of 5 and above in ascending order
IntStream stream = Arrays.stream(values);
stream.filter(v -> v >= 5).sorted().forEach(v -> System.out.print(v + " "));
}
}
4-2.Max,Min,Average
C#
private void button2_Click(object sender, EventArgs e)
{
int[] values = new int[] { 2, 5, 3, 1, 8, 4, 2 };
var max = values.Max();
var min = values.Min();
var avg = values.Average();
Console.WriteLine($"Max={max}, Min={min}, Average={avg}");
}
Java
import java.util.Arrays;
public class Sample {
public static void main(String[] args) {
int[] values = new int[] { 2, 5, 3, 1, 8, 4, 2, 6 };
int max = Arrays.stream(values).max().getAsInt();
int min = Arrays.stream(values).min().getAsInt();
double avg = Arrays.stream(values).average().getAsDouble();
System.out.println(String.format("max=%d, min=%d, average=%f", max, min, avg));
}
}
Linq is a lazy execution, but it's a bit confusing and can lead to bugs, so I'll sort it out.
As a sample, a program was created in which the numerical values from 1 to 10 were multiplied by 5, only even numbers were extracted, and the total was calculated.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Class1
{
internal static void Main(string[] args)
{
int[] numbers = Enumerable.Range(1, 10).ToArray();
IEnumerable<int> number5 = numbers.Select(n =>
{
Console.WriteLine($"{n}Is multiplied by 5.");
return n * 5;
});
Console.WriteLine("5 times processing finished?");
IEnumerable<int> even = number5.Where(n =>
{
Console.WriteLine($"{n}Is even.");
return n % 2 == 0;
});
Console.WriteLine("Is it even number?");
int sum = even.SumNumber();
Console.WriteLine($"The total is{sum}");
}
}
public static class SumSample
{
public static int SumNumber(this IEnumerable<int> numbers)
{
Console.WriteLine("Sum processing started");
int sum = 0;
foreach(var n in numbers)
{
sum += n;
Console.WriteLine($"{n}Add.(sum:{sum})");
}
Console.WriteLine("Sum processing finished");
return sum;
}
}
}
result
5 times processing finished?
Is it even number?
Sum processing started
Multiply 1 by 5.
Determine if 5 is even.
Multiply 2 by 5.
Determine if 10 is an even number.
Add 10.(sum:10)
Multiply 3 by 5.
Determine if 15 is an even number.
Multiply 4 by 5.
Determine if 20 is an even number.
Add 20.(sum:30)
Multiply 5 by 5.
Determine if 25 is an even number.
Multiply 6 by 5.
Determine if 30 is an even number.
Add 30.(sum:60)
Multiply 7 by 5.
Determine if 35 is an even number.
Multiply 8 by 5.
Determine if 40 is an even number.
Add 40.(sum:100)
Multiply 9 by 5.
Determine if 45 is an even number.
Multiply 10 by 5.
Determine if 50 is an even number.
Add 50.(sum:150)
Sum processing finished
150 in total
I try to output to the Console in the loop, but it doesn't move like "First perform the process of multiplying the value by 5 and then perform the process of extracting after that ...". The process has been executed since it was needed for SumNumber processing. (Delayed execution)
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Class1
{
internal static void Main(string[] args)
{
int[] numbers = Enumerable.Range(1, 10).ToArray();
IEnumerable<int> number5 = numbers.Select(n =>
{
Console.WriteLine($"{n}Is multiplied by 5.");
return n * 5;
}).ToArray(); //Immediate execution
Console.WriteLine("5 times processing finished?");
IEnumerable<int> even = number5.Where(n =>
{
Console.WriteLine($"{n}Is even.");
return n % 2 == 0;
}).ToArray(); //Immediate execution
Console.WriteLine("Is it even number?");
int sum = even.SumNumber();
Console.WriteLine($"The total is{sum}");
}
}
public static class SumSample
{
public static int SumNumber(this IEnumerable<int> numbers)
{
Console.WriteLine("Sum processing started");
int sum = 0;
foreach(var n in numbers)
{
sum += n;
Console.WriteLine($"{n}Add.(sum:{sum})");
}
Console.WriteLine("Sum processing finished");
return sum;
}
}
}
result
Multiply 1 by 5.
Multiply 2 by 5.
Multiply 3 by 5.
Multiply 4 by 5.
Multiply 5 by 5.
Multiply 6 by 5.
Multiply 7 by 5.
Multiply 8 by 5.
Multiply 9 by 5.
Multiply 10 by 5.
5 times processing finished?
Determine if 5 is even.
Determine if 10 is an even number.
Determine if 15 is an even number.
Determine if 20 is an even number.
Determine if 25 is an even number.
Determine if 30 is an even number.
Determine if 35 is an even number.
Determine if 40 is an even number.
Determine if 45 is an even number.
Determine if 50 is an even number.
Is it even number?
Sum processing started
Add 10.(sum:10)
Add 20.(sum:30)
Add 30.(sum:60)
Add 40.(sum:100)
Add 50.(sum:150)
Sum processing finished
150 in total
To execute immediately, add ToArray or ToList.
Intuitively difficult to understand. In the example below, 5 or more are extracted from the list containing the values 2,4,6,8. Note that not only 6 and 8 are extracted, but 7 added after that is also extracted.
C#
private void button1_Click(object sender, EventArgs e)
{
List<int> list = new List<int> { 2, 4, 6, 8 };
var result = list.Where(x => x > 5);
list.Add(3);
list.Add(7);
Console.WriteLine(string.Join(",", result));
}
result
6,8,7
Number 5 and even in 5-1 have no substance. Just call it when you need it and return the value.
Recommended Posts