java.util.Collectors vs. System.Linq.Enumerable

# 動機

C# には java の Stream API に相当する Linq があるが、いまひとつ使いこなせなかったため、
java で出来ていたこういう処理を C# で書くとどうなるのか？　についてのメモを残そうと思い立った.

おそらく初めての言語として C# を選んだ人にとっては役に立たないだろう.

# 具体例

「java でこう書くとこのような結果が出る」というのを書き、その後ろに C# での書き方の一例を示していく.

## 例に使用するコード

```java:java sample
public class Program {
  public static void main(String[] args) {
    List<Data> list = createDataList();

    // T resultXX = list.stream().collect(Collectors.XXX());
    // System.out.println("resultXX=" + resultXX);
  }
  
  private static List<Data> createDataList() {
    List<Data> list = new ArrayList<>();
    list.add(new Data( 0, "Francisco", "Mahoney", 38));
    list.add(new Data( 1, "Michelle", "Larson", 37));
    list.add(new Data( 2, "Wendy", "Reese", 23));
    list.add(new Data( 3, "Haris", "Holden", 37));
    list.add(new Data( 4, "April", "Martin", 44));
    list.add(new Data( 5, "Dustin", "Simmons", 28));
    list.add(new Data( 6, "Portia", "Bowman", 31));
    list.add(new Data( 7, "Clare", "Larson", 13));
    list.add(new Data( 8, "Rachel", "Smith", 40));
    list.add(new Data( 9, "Ryan", "Hayes", 66));
    list.add(new Data(10, "Tala", "Rennie", 49));
    list.add(new Data(11, "April", "Johnson", 76));
    list.add(new Data(12, "Steven", "Sloan", 12));
    list.add(new Data(13, "Angelica", "Cordova", 12));
    list.add(new Data(14, "Leslie", "Smith", 37));
    list.add(new Data(15, "Anthony", "Carter", 33));
    list.add(new Data(16, "Christine", "Bowman", 31));
    list.add(new Data(17, "Bethaney", "Deacon", 15));
    list.add(new Data(18, "Gabija", "Blackmore", 20));
    list.add(new Data(19, "Mary", "Larson", 39));
    return list;
  }
}

class Data {
  private final int id;
  private final String firstName;
  private final String lastName;
  private final int age;
  
  // 以下のメソッドは省略
  // constructor
  // @Override public boolean equals(Object o)
  // @Override public int hashCode()
  // @Override public String toString()
  // getter/setter
}
```

```C#:C# sample
public static class Program {
  public static void Main(string[] args) {
    List<Data> list = CreateDataList();

    // // C# の List などは ToString() が実装されていないので、適当な処理を作成した.
    // T resultXX = list.XXX();
    // Console.WriteLine("resultXX=" + ToString(resultXX));
  }
  private static List<Data> CreateDataList() {
    return new List<Data>() {
      new Data(0, "Francisco", "Mahoney", 38)
      , new Data(1, "Michelle", "Larson", 37)
      , new Data(2, "Wendy", "Reese", 23)
      , new Data(3, "Haris", "Holden", 37)
      , new Data(4, "April", "Martin", 44)
      , new Data(5, "Dustin", "Simmons", 28)
      , new Data(6, "Portia", "Bowman", 31)
      , new Data(7, "Clare", "Larson", 13)
      , new Data(8, "Rachel", "Smith", 40)
      , new Data(9, "Ryan", "Hayes", 66)
      , new Data(10, "Tala", "Rennie", 49)
      , new Data(11, "April", "Johnson", 76)
      , new Data(12, "Steven", "Sloan", 12)
      , new Data(13, "Angelica", "Cordova", 12)
      , new Data(14, "Leslie", "Smith", 37)
      , new Data(15, "Anthony", "Carter", 33)
      , new Data(16, "Christine", "Bowman", 31)
      , new Data(17, "Bethaney", "Deacon", 15)
      , new Data(18, "Gabija", "Blackmore", 20)
      , new Data(19, "Mary", "Larson", 39)
    };
  }
}

public struct Data {
  public int Id { get; }
  public string FirstName { get; }
  public string LastName { get; }
  public int Age { get; }

  // 以下のメソッドは省略
  // constructor
  // override public bool Equals([NotNullWhen(true)] object? obj)
  // override public int GetHashCode()
  // override public string ToString()
}
```

## java.util.Collectors に存在する各メソッド

### counting
- counting()

java は long だけだが、C# では int, long 2種類のメソッドが用意されている.

```java:java sample
long result04 = list.stream().collect(Collectors.counting());

// result04=20
```

```C#:C# sample
int result04_0 = list.Count();
long result04_1 = list.LongCount();

// result04_0=20
// result04_1=20
```

### joining
- joining()
- joining(CharSequence delimiter)
- joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

java では Iterable と Stream がはっきり分かれているためか、Stream API に文字列化用の処理を用意してある.
一方 C# ではどちらも IEnumerable であるから、わざわざ Linq での処理を用意するようなことはしていないようだ.

```java:java sample
String result11 = list.stream().map(Data::toString).collect(Collectors.joining());
String result12 = list.stream().map(Data::toString).collect(Collectors.joining(", "));
String result13 = list.stream().map(Data::toString).collect(Collectors.joining(", ", "prefix [", "] suffix"));

// result11=Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]Data[id=1, firstName=Michelle, lastName=Larson, age=37]Data[id=2, firstName=Wendy, lastName=Reese, age=23]Data[id=3, firstName=Haris, lastName=Holden, age=37]Data[id=4, firstName=April, lastName=Martin, age=44]Data[id=5, firstName=Dustin, lastName=Simmons, age=28]Data[id=6, firstName=Portia, lastName=Bowman, age=31]Data[id=7, firstName=Clare, lastName=Larson, age=13]Data[id=8, firstName=Rachel, lastName=Smith, age=40]Data[id=9, firstName=Ryan, lastName=Hayes, age=66]Data[id=10, firstName=Tala, lastName=Rennie, age=49]Data[id=11, firstName=April, lastName=Johnson, age=76]Data[id=12, firstName=Steven, lastName=Sloan, age=12]Data[id=13, firstName=Angelica, lastName=Cordova, age=12]Data[id=14, firstName=Leslie, lastName=Smith, age=37]Data[id=15, firstName=Anthony, lastName=Carter, age=33]Data[id=16, firstName=Christine, lastName=Bowman, age=31]Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]Data[id=19, firstName=Mary, lastName=Larson, age=39]
// result12=Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]
// result13=prefix [Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]] suffix
```

```C#:C# sample
string result11 = string.Join("", list);
string result12 = string.Join(", ", list);
string result13 = "prefix [" + string.Join(", ", list) + "] suffix";

// result11=Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]Data[id=1, firstName=Michelle, lastName=Larson, age=37]Data[id=2, firstName=Wendy, lastName=Reese, age=23]Data[id=3, firstName=Haris, lastName=Holden, age=37]Data[id=4, firstName=April, lastName=Martin, age=44]Data[id=5, firstName=Dustin, lastName=Simmons, age=28]Data[id=6, firstName=Portia, lastName=Bowman, age=31]Data[id=7, firstName=Clare, lastName=Larson, age=13]Data[id=8, firstName=Rachel, lastName=Smith, age=40]Data[id=9, firstName=Ryan, lastName=Hayes, age=66]Data[id=10, firstName=Tala, lastName=Rennie, age=49]Data[id=11, firstName=April, lastName=Johnson, age=76]Data[id=12, firstName=Steven, lastName=Sloan, age=12]Data[id=13, firstName=Angelica, lastName=Cordova, age=12]Data[id=14, firstName=Leslie, lastName=Smith, age=37]Data[id=15, firstName=Anthony, lastName=Carter, age=33]Data[id=16, firstName=Christine, lastName=Bowman, age=31]Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]Data[id=19, firstName=Mary, lastName=Larson, age=39]
// result12=Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]
// result13=prefix [Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]] suffix
```

### maxBy, minBy
- maxBy(Comparator\<? super T> comparator)
- minBy(Comparator\<? super T> comparator)

java の Comparator に比べて C# の Comparer が使いづらいように思われることを除けば大差ないだろう.

```java:java sample
Optional<Data> result15 = list.stream().collect(Collectors.maxBy(Comparator.comparing(Data::getAge)));
Optional<Data> result16 = list.stream().collect(Collectors.minBy(Comparator.comparing(Data::getAge)));

// result15=Optional[Data[id=11, firstName=April, lastName=Johnson, age=76]]
// result16=Optional[Data[id=12, firstName=Steven, lastName=Sloan, age=12]]
```

```C#:C# sample
Data result15_0 = list.Max(Comparer<Data>.Create((a, b) => a.Age - b.Age));
Data result15_1 = list.MaxBy(x => x.Age);
Data result16_0 = list.Min(Comparer<Data>.Create((a, b) => a.Age - b.Age));
Data result16_1 = list.MinBy(x => x.Age);

// result15_0=Data[id=11, firstName=April, lastName=Johnson, age=76]
// result15_1=Data[id=11, firstName=April, lastName=Johnson, age=76]
// result16_0=Data[id=12, firstName=Steven, lastName=Sloan, age=12]
// result16_1=Data[id=12, firstName=Steven, lastName=Sloan, age=12]
```

### averagingXX
- averagingDouble(ToDoubleFunction\<? super T> mapper)
- averagingInt(ToIntFunction\<? super T> mapper)
- averagingLong(ToLongFunction\<? super T> mapper)

どちらも同じように扱える.
強いて言えば、C# には decimal 型用の Average がある位だろうか.

```java:java sample
double result00 = list.stream().collect(Collectors.averagingDouble(Data::getAge));
double result01 = list.stream().collect(Collectors.averagingInt(Data::getAge));
double result02 = list.stream().collect(Collectors.averagingLong(Data::getAge));

// result00=34.05
// result01=34.05
// result02=34.05
```

```C#:C# sample
double result00 = list.Average(x => (double) x.Age);
double result01 = list.Average(x => x.Age);
double result02 = list.Average(x => (long) x.Age);

// result00=34.05
// result01=34.05
// result02=34.05
```

### summingXX
- summingDouble(ToDoubleFunction\<? super T> mapper)
- summingInt(ToIntFunction\<? super T> mapper)
- summingLong(ToLongFunction\<? super T> mapper)

Average 同様どちらも同じように扱える.
こちらも、C# には decimal 型用の Sum がある.

```java:java sample
double result25 = list.stream().collect(Collectors.summingDouble(Data::getAge));
int result26 = list.stream().collect(Collectors.summingInt(Data::getAge));
long result27 = list.stream().collect(Collectors.summingLong(Data::getAge));

// result25=681.0
// result26=681
// result27=681
```

```C#:C# sample
double result25 = list.Sum(x => (double) x.Age);
int result26 = list.Sum(x => x.Age);
long result27 = list.Sum(x => (long) x.Age);

// result25=681
// result26=681
// result27=681
```

### summarizingXX
- summarizingDouble(ToDoubleFunction\<? super T> mapper)
- summarizingInt(ToIntFunction\<? super T> mapper)
- summarizingLong(ToLongFunction\<? super T> mapper)

正直 java がわざわざ用意しているのが不思議なくらいの処理であるから、C# にないのも蓋し当然といえる.
ここでは Linq に用意されている汎用処理である Aggregate から同様の結果を得ている.

```java:java sample
DoubleSummaryStatistics result22 = list.stream().collect(Collectors.summarizingDouble(Data::getAge));
IntSummaryStatistics result23 = list.stream().collect(Collectors.summarizingInt(Data::getAge));
LongSummaryStatistics result24 = list.stream().collect(Collectors.summarizingLong(Data::getAge));

// result22=DoubleSummaryStatistics{count=20, sum=681.000000, min=12.000000, average=34.050000, max=76.000000}
// result23=IntSummaryStatistics{count=20, sum=681, min=12, average=34.050000, max=76}
// result24=LongSummaryStatistics{count=20, sum=681, min=12, average=34.050000, max=76}
```

```C#:C# sample
(int count, double sum, double min, double max, double average) result22 = list.Select(x => (double) x.Age).Aggregate<double, (int count, double sum, double min, double max), (int count, double sum, double min, double max, double average)>((0, 0.0, double.PositiveInfinity, double.NegativeInfinity), (a, b) => (a.count + 1, a.sum + b, Math.Min(a.min, b), Math.Max(a.max, b)), summary => (summary.count, summary.sum, summary.min, summary.max, summary.sum / summary.count));
(int count, int sum, int min, int max, double average) result23 = list.Select(x => x.Age).Aggregate<int, (int count, int sum, int min, int max), (int count, int sum, int min, int max, double average)>((0, 0, int.MaxValue, int.MinValue), (a, b) => (a.count + 1, a.sum + b, Math.Min(a.min, b), Math.Max(a.max, b)), summary => (summary.count, summary.sum, summary.min, summary.max, (double) summary.sum / summary.count));
(int count, long sum, long min, long max, double average) result24 = list.Select(x => (long) x.Age).Aggregate<long, (int count, long sum, long min, long max), (int count, long sum, long min, long max, double average)>((0, 0L, long.MaxValue, long.MinValue), (a, b) => (a.count + 1, a.sum + b, Math.Min(a.min, b), Math.Max(a.max, b)), summary => (summary.count, summary.sum, summary.min, summary.max, (double) summary.sum / summary.count));

// result22=(20, 681, 12, 76, 34.05)
// result23=(20, 681, 12, 76, 34.05)
// result24=(20, 681, 12, 76, 34.05)
```

### toList
- toList()

```java:java sample
List<Data> result32 = list.stream().collect(Collectors.toList());

// result32=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

```C#:C# sample
List<Data> result32 = list.ToList();

// result32=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

### toSet
- toSet()

```java:java sample
Set<Data> result36 = list.stream().collect(Collectors.toSet());

// result36=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

```C#:C# sample
HashSet<Data> result36 = list.ToHashSet();

// result36=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

### toCollection
- toCollection(Supplier\<C> collectionFactory)

java では好きな Collection を Stream から生成できるが、C# ではストリーム処理から続けて ICollection を簡単に構築する方法がない.
C# では、目的の ICollection が持つ IEnumerable を引数とするコンストラクタを使うか、あるいは汎用の Aggregate で第二引数に {xs.Add(x); return xs}、第三引数に恒等関数をそれぞれ指定してやる必要がある.
このような処理を実際使うことはあまりないかもしれないが、しかし何度もその ICollection を作らなければならない場合は自分用に拡張メソッドを書いてやらねばならないのだろうか.

```java:java sample
LinkedList<Data> result37 = list.stream().collect(Collectors.toCollection(LinkedList::new));

// result37=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

```C#:C# sample
LinkedList<Data> result37_0 = new LinkedList<Data>(list);
LinkedList<Data> result37_1 = list.Aggregate(new LinkedList<Data>(), (xs, x) => { (xs as ICollection<Data>).Add(x); return xs; }, xs => xs);

// result37_0=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
// result37_1=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=19, firstName=Mary, lastName=Larson, age=39]]
```

### toConcurrentMap
- toConcurrentMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper)
- toConcurrentMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper, BinaryOperator\<U> mergeFunction)
- toConcurrentMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper, BinaryOperator\<U> mergeFunction, Supplier\<M> mapSupplier)

C# では Dictionary から構築しなければならない？

```java:java sample
ConcurrentMap<Integer, String> result29 = list.stream().collect(Collectors.toConcurrentMap(Data::getId, Data::getLastName));
ConcurrentMap<Integer, String> result30 = list.stream().collect(Collectors.toConcurrentMap(Data::getId, Data::getLastName, (__, ___) -> { throw new UnsupportedOperationException("Cannot merge"); }));
ConcurrentSkipListMap<Integer, String> result31 = list.stream().collect(Collectors.toConcurrentMap(Data::getId, Data::getLastName, (__, ___) -> { throw new UnsupportedOperationException("Cannot merge"); }, ConcurrentSkipListMap::new));

// result29={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
// result30={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
// result31={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
```

```C#:C# sample
ConcurrentDictionary<int, string> result29 = new ConcurrentDictionary<int, string>(list.ToDictionary(x => x.Id, x => x.LastName));
ConcurrentDictionary<int, string> result30 = new ConcurrentDictionary<int, string>(list.ToDictionary(x => x.Id, x => x.LastName));
ConcurrentDictionary<int, string> result31 = new ConcurrentDictionary<int, string>(list.ToDictionary(x => x.Id, x => x.LastName));

// result29=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
// result30=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
// result31=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
```

### toMap
- toMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper)
- toMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper, BinaryOperator\<U> mergeFunction)
- toMap(Function\<? super T,? extends K> keyMapper, Function\<? super T,? extends U> valueMapper, BinaryOperator\<U> mergeFunction, Supplier\<M> mapSupplier)

java の方の引数にある mergeFunction は並列処理用の関数であるから今回の例において result33 と result34 は同値である.
\#toCollection の所にも同様のことを書いたが、C# では好きな IDictionary をストリーム処理の結果として作ることがあまり考慮されていないようだ.
そもそも java が Map というインターフェースで返すのに対して、C# は Dictionary というクラスで返している.
インターフェースに対するプログラミングをモットーとするオブジェクト指向としてはイマイチな設計といえるのではないだろうか.
デコレータパターンなどに対する否定とも取られかねない. C# は IDictionary を何だと考えているのか.

```java:java sample
Map<Integer, String> result33 = list.stream().collect(Collectors.toMap(Data::getId, Data::getLastName));
Map<Integer, String> result34 = list.stream().collect(Collectors.toMap(Data::getId, Data::getLastName, (__, ___) -> { throw new UnsupportedOperationException("Cannot merge"); }));
TreeMap<Integer, String> result35 = list.stream().collect(Collectors.toMap(Data::getId, Data::getLastName, (__, ___) -> { throw new UnsupportedOperationException("Cannot merge"); }, TreeMap::new));

// result33={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
// result34={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
// result35={0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson}
```

```C#:C# sample
Dictionary<int, string> result33 = list.ToDictionary(x => x.Id, x => x.LastName);
Dictionary<int, string> result34 = list.ToDictionary(x => x.Id, x => x.LastName);
SortedDictionary<int, string> result35 = new SortedDictionary<int, string>(list.ToDictionary(x => x.Id, x => x.LastName));

// result33=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
// result34=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
// result35=0=Mahoney, 1=Larson, 2=Reese, 3=Holden, 4=Martin, 5=Simmons, 6=Bowman, 7=Larson, 8=Smith, 9=Hayes, 10=Rennie, 11=Johnson, 12=Sloan, 13=Cordova, 14=Smith, 15=Carter, 16=Bowman, 17=Deacon, 18=Blackmore, 19=Larson
```

今回は list からそのまま構築しているが、C# sample の result35 のような書き方を実際に用いる場合、

1. SortedDictionary をこういうデータから構築する.
1. こういうデータというのは list を元にして、
1. このような条件で絞って(Where)、
1. このような変換をして(Select)
1. その結果これを Key、あれを Value として得られるものである

のような語順になってしまう.
一方 java の場合、

1. list を元にして、
1. このような条件で絞って(filter)、
1. このような変換をして(map)
1. これを Key、あれを Value とする
1. TreeMap を構築する.

のように書け、こちらの方が自然ではないだろうか？　(mergeFunction 部分が邪魔だけれども)
Stream API、ないし Linq の流れるような記述を邪魔しないためにも、ストレスのない書き方ができるべきだろう.

### partitioningBy
- partitioningBy(Predicate\<? super T> predicate)
- partitioningBy(Predicate\<? super T> predicate, Collector\<? super T,A,D> downstream)

正直 java でも groupingBy で十分な気がするのだが、group と partition の意味上の違いがそれほど大きいのだろうか？

```java:java sample
Map<Boolean, List<Data>> result17 = list.stream().collect(Collectors.partitioningBy(x -> x.getAge() < 30));
Map<Boolean, Set<Data>> result18 = list.stream().collect(Collectors.partitioningBy(x -> x.getAge() < 30, Collectors.toSet()));

// result17={false=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=19, firstName=Mary, lastName=Larson, age=39]], true=[Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]]}
// result18={false=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=19, firstName=Mary, lastName=Larson, age=39]], true=[Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=5, firstName=Dustin, lastName=Simmons, age=28]]}
```

```C#:C# sample
Dictionary<bool, List<Data>> result17 = list.GroupBy(x => x.Age < 30).ToDictionary(g => g.Key, g => g.ToList());
Dictionary<bool, HashSet<Data>> result18 = list.GroupBy(x => x.Age < 30).ToDictionary(g => g.Key, g => g.ToHashSet());

// result17=False=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=19, firstName=Mary, lastName=Larson, age=39]], True=[Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]]
// result18=False=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=19, firstName=Mary, lastName=Larson, age=39]], True=[Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]]
```

### groupingBy
- groupingBy(Function\<? super T,? extends K> classifier)
- groupingBy(Function\<? super T,? extends K> classifier, Collector\<? super T,A,D> downstream)
- groupingBy(Function\<? super T,? extends K> classifier, Supplier\<M> mapFactory, Collector\<? super T,A,D> downstream)

java の groupingBy は Map を返すが、C# の GroupBy は IEnumerable\<IGrouping\<TKey, TSource>> を返す.
例では使っていないが、C# には GroupBy とほぼ同様に使える ToLookup というものもある.

```java:java sample
Map<String, List<Data>> result05 = list.stream().collect(Collectors.groupingBy(Data::getLastName));
Map<String, Set<Data>> result06 = list.stream().collect(Collectors.groupingBy(Data::getLastName, Collectors.toSet()));
TreeMap<String, Set<Data>> result07 = list.stream().collect(Collectors.groupingBy(Data::getLastName, () -> new TreeMap<>(), Collectors.toSet()));

// result05={Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]]}
// result06={Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Larson=[Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]]}
// result07={Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Larson=[Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]]}
```

```C#:C# sample
IEnumerable<IGrouping<string, Data>> result05_0 = list.GroupBy(x => x.LastName);
Dictionary<string, List<Data>> result05_1 = list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToList());
Dictionary<string, HashSet<Data>> result06 = list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToHashSet());
SortedDictionary<string, HashSet<Data>> result07 = new SortedDictionary<string, HashSet<Data>>(list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToHashSet()));

// result05_0=[System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data], System.Linq.Grouping`2[System.String,LinqStudies.Data]]
// result05_1=Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]]
// result06=Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]]
// result07=Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]]
```

### groupingByConcurrent
- groupingByConcurrent(Function\<? super T,? extends K> classifier)
- groupingByConcurrent(Function\<? super T,? extends K> classifier, Collector\<? super T,A,D> downstream)
- groupingByConcurrent(Function\<? super T,? extends K> classifier, Supplier\<M> mapFactory, Collector\<? super T,A,D> downstream)

```java:java sample
ConcurrentMap<String, List<Data>> result08 = list.stream().collect(Collectors.groupingByConcurrent(Data::getLastName));
ConcurrentMap<String, Set<Data>> result09 = list.stream().collect(Collectors.groupingByConcurrent(Data::getLastName, Collectors.toSet()));
ConcurrentSkipListMap<String, Set<Data>> result10 = list.stream().collect(Collectors.groupingByConcurrent(Data::getLastName, ConcurrentSkipListMap::new, Collectors.toSet()));

// result08={Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]]}
// result09={Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Larson=[Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]]}
// result10={Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Larson=[Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]]}
```

```C#:C# sample
ConcurrentDictionary<string, List<Data>> result08 = new ConcurrentDictionary<string, List<Data>>(list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToList()));
ConcurrentDictionary<string, HashSet<Data>> result09 = new ConcurrentDictionary<string, HashSet<Data>>(list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToHashSet()));
ConcurrentDictionary<string, HashSet<Data>> result10 = new ConcurrentDictionary<string, HashSet<Data>>(list.GroupBy(x => x.LastName).ToDictionary(g => g.Key, g => g.ToHashSet()));

// result08=Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]]
// result09=Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]]
// result10=Blackmore=[Data[id=18, firstName=Gabija, lastName=Blackmore, age=20]], Larson=[Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=19, firstName=Mary, lastName=Larson, age=39]], Deacon=[Data[id=17, firstName=Bethaney, lastName=Deacon, age=15]], Mahoney=[Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]], Rennie=[Data[id=10, firstName=Tala, lastName=Rennie, age=49]], Holden=[Data[id=3, firstName=Haris, lastName=Holden, age=37]], Carter=[Data[id=15, firstName=Anthony, lastName=Carter, age=33]], Cordova=[Data[id=13, firstName=Angelica, lastName=Cordova, age=12]], Martin=[Data[id=4, firstName=April, lastName=Martin, age=44]], Bowman=[Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=16, firstName=Christine, lastName=Bowman, age=31]], Reese=[Data[id=2, firstName=Wendy, lastName=Reese, age=23]], Simmons=[Data[id=5, firstName=Dustin, lastName=Simmons, age=28]], Hayes=[Data[id=9, firstName=Ryan, lastName=Hayes, age=66]], Smith=[Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=14, firstName=Leslie, lastName=Smith, age=37]], Johnson=[Data[id=11, firstName=April, lastName=Johnson, age=76]], Sloan=[Data[id=12, firstName=Steven, lastName=Sloan, age=12]]
```

### reducing
- reducing(BinaryOperator\<T> op)
- reducing(T identity, BinaryOperator\<T> op)
- reducing(U identity, Function\<? super T,? extends U> mapper, BinaryOperator\<U> op)

C# では Aggregate で同様に処理できる.

```java:java sample
Optional<Data> result19 = list.stream().collect(Collectors.reducing((a, b) -> new Data(a.getId() + b.getId(), a.getFirstName() + b.getFirstName(), a.getLastName() + b.getLastName(), a.getAge() + b.getAge())));
Data result20 = list.stream().collect(Collectors.reducing(new Data(100, "FIRST_NAME", "LAST_NAME", 0), (a, b) -> new Data(a.getId() + b.getId(), a.getFirstName() + b.getFirstName(), a.getLastName() + b.getLastName(), a.getAge() + b.getAge())));
int result21 = list.stream().collect(Collectors.reducing(0, Data::getAge, (a, b) -> a + b));

// result19=Optional[Data[id=190, firstName=FranciscoMichelleWendyHarisAprilDustinPortiaClareRachelRyanTalaAprilStevenAngelicaLeslieAnthonyChristineBethaneyGabijaMary, lastName=MahoneyLarsonReeseHoldenMartinSimmonsBowmanLarsonSmithHayesRennieJohnsonSloanCordovaSmithCarterBowmanDeaconBlackmoreLarson, age=681]]
// result20=Data[id=290, firstName=FIRST_NAMEFranciscoMichelleWendyHarisAprilDustinPortiaClareRachelRyanTalaAprilStevenAngelicaLeslieAnthonyChristineBethaneyGabijaMary, lastName=LAST_NAMEMahoneyLarsonReeseHoldenMartinSimmonsBowmanLarsonSmithHayesRennieJohnsonSloanCordovaSmithCarterBowmanDeaconBlackmoreLarson, age=681]
// result21=681
```

```C#:C# sample
Data result19 = list.Aggregate((a, b) => new Data(a.Id + b.Id, a.FirstName + b.FirstName, a.LastName + b.LastName, a.Age + b.Age));
Data result20 = list.Aggregate(new Data(100, "FIRST_NAME", "LAST_NAME", 0), (a, b) => new Data(a.Id + b.Id, a.FirstName + b.FirstName, a.LastName + b.LastName, a.Age + b.Age));
int result21 = list.Select(x => x.Age).Aggregate(0, (a, b) => a + b);

// result19=Data[id=190, firstName=FranciscoMichelleWendyHarisAprilDustinPortiaClareRachelRyanTalaAprilStevenAngelicaLeslieAnthonyChristineBethaneyGabijaMary, lastName=MahoneyLarsonReeseHoldenMartinSimmonsBowmanLarsonSmithHayesRennieJohnsonSloanCordovaSmithCarterBowmanDeaconBlackmoreLarson, age=681]
// result20=Data[id=290, firstName=FIRST_NAMEFranciscoMichelleWendyHarisAprilDustinPortiaClareRachelRyanTalaAprilStevenAngelicaLeslieAnthonyChristineBethaneyGabijaMary, lastName=LAST_NAMEMahoneyLarsonReeseHoldenMartinSimmonsBowmanLarsonSmithHayesRennieJohnsonSloanCordovaSmithCarterBowmanDeaconBlackmoreLarson, age=681]
// result21=681
```

### mapping
- mapping(Function\<? super T,? extends U> mapper, Collector\<? super U,A,R> downstream)

java でも map(mapper).collect(downstream) と同じ動作であるから特筆すべき点はない.
いまひとつ使いどころが分からない.

```java:java sample
List<Integer> result14 = list.stream().collect(Collectors.mapping(Data::getId, Collectors.toList()));

// result14=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
```

```C#:C# sample
List<int> result14 = list.Select(x => x.Id).ToList();

// result14=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
```

### collectingAndThen
- collectingAndThen(Collector\<T,A,R> downstream, Function\<R,RR> finisher)

C# では一度 downstream 相当の処理を終わらせてから finisher 相当の処理を実施する(result03_0)、
あるいは Aggregate を用いて一回で処理しきる(result_03_1)かのどちらかである.

前者の場合は前段の結果を受ける変数/行と後段の結果を受ける変数/行とが必要であり、役割の薄い変数/行が現れてしまう.
後者の場合はわざわざ既存の downstream を Aggregate で使えるように分解してやらねばならない.
こう見ると java.util.stream.Collector というレイヤーの重要性が感じられるかもしれない.

```java:java sample
List<Data> result03 = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), xs -> { Collections.reverse(xs); return xs; }));

// result03=[Data[id=19, firstName=Mary, lastName=Larson, age=39], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]]
```

```C#:C# sample
List<Data> result03_0 = list.ToList();
result03_0.Reverse();

List<Data> result03_1 = list.Aggregate(new List<Data>(), (xs, x) => { xs.Add(x); return xs; }, xs => { xs.Reverse(); return xs; });

// result03_0=[Data[id=19, firstName=Mary, lastName=Larson, age=39], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]]
// result03_1=[Data[id=19, firstName=Mary, lastName=Larson, age=39], Data[id=18, firstName=Gabija, lastName=Blackmore, age=20], Data[id=17, firstName=Bethaney, lastName=Deacon, age=15], Data[id=16, firstName=Christine, lastName=Bowman, age=31], Data[id=15, firstName=Anthony, lastName=Carter, age=33], Data[id=14, firstName=Leslie, lastName=Smith, age=37], Data[id=13, firstName=Angelica, lastName=Cordova, age=12], Data[id=12, firstName=Steven, lastName=Sloan, age=12], Data[id=11, firstName=April, lastName=Johnson, age=76], Data[id=10, firstName=Tala, lastName=Rennie, age=49], Data[id=9, firstName=Ryan, lastName=Hayes, age=66], Data[id=8, firstName=Rachel, lastName=Smith, age=40], Data[id=7, firstName=Clare, lastName=Larson, age=13], Data[id=6, firstName=Portia, lastName=Bowman, age=31], Data[id=5, firstName=Dustin, lastName=Simmons, age=28], Data[id=4, firstName=April, lastName=Martin, age=44], Data[id=3, firstName=Haris, lastName=Holden, age=37], Data[id=2, firstName=Wendy, lastName=Reese, age=23], Data[id=1, firstName=Michelle, lastName=Larson, age=37], Data[id=0, firstName=Francisco, lastName=Mahoney, age=38]]
```