一、Optional

    Java应用中最常见的bug就是空值异常。在Java 8之前,Google Guava引入了Optionals类来解决NullPointerException,从而避免源码被各种null检查污染,以便开发者写出更加整洁的代码。Java 8也将Optional加入了官方库。

    Optional仅仅是一个容易:存放T类型的值或者null。它提供了一些有用的接口来避免显式的null检查。

API:

Modifier and Type Method and Description
static <T> Optional<T> empty()

返回一个空的 Optional实例。

boolean equals(Object obj)

指示某个其他对象是否等于此可选项。

Optional<T> filter(Predicate<? super T> predicate)

如果一个值存在,并且该值给定的谓词相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 。

<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

如果一个值存在,应用提供的 Optional映射函数给它,返回该结果,否则返回一个空的 Optional 。

T get()

如果 Optional中有一个值,返回值,否则抛出 NoSuchElementException 。

int hashCode()

返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。

void ifPresent(Consumer<? super T> consumer)

如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。

boolean isPresent()

返回 true如果存在值,否则为 false 。

<U> Optional<U> map(Function<? super T,? extends U> mapper)

如果存在一个值,则应用提供的映射函数,如果结果不为空,则返回一个 Optional结果的 Optional 。

static <T> Optional<T> of(T value)

返回具有 Optional的当前非空值的Optional。

static <T> Optional<T> ofNullable(T value)

返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 。

T orElse(T other)

返回值如果存在,否则返回 other 。

T orElseGet(Supplier<? extends T> other)

返回值(如果存在),否则调用 other并返回该调用的结果。

<X extends Throwable>
T
orElseThrow(Supplier<? extends X> exceptionSupplier)

返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。

String toString()

返回此可选的非空字符串表示,适用于调试。 


二、Stream

参考:

http://blog.csdn.net/u010425776/article/details/52344425

http://blog.csdn.net/u010425776/article/details/52346644

API:

Modifier and Type Method and Description
boolean allMatch(Predicate<? super T> predicate)

返回此流的所有元素是否与提供的谓词匹配。

boolean anyMatch(Predicate<? super T> predicate)

返回此流的任何元素是否与提供的谓词匹配。

static <T> Stream.Builder<T> builder()

返回一个 Stream的构建器。

<R,A> R collect(Collector<? super T,A,R> collector)

使用 Collector对此流的元素执行 mutable reduction Collector 。

<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)

对此流的元素执行 mutable reduction操作。

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)

创建一个懒惰连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。

long count()

返回此流中的元素数。

Stream<T> distinct()

返回由该流的不同元素(根据 Object.equals(Object) )组成的流。

static <T> Stream<T> empty()

返回一个空的顺序 Stream 。

Stream<T> filter(Predicate<? super T> predicate)

返回由与此给定谓词匹配的此流的元素组成的流。

Optional<T> findAny()

返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional 。

Optional<T> findFirst()

返回描述此流的第一个元素的Optional如果流为空,则返回一个空的Optional 。

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

返回由通过将提供的映射函数应用于每个元素而产生的映射流的内容来替换该流的每个元素的结果的流。

DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)

返回一个 DoubleStream ,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。

IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper)

返回一个 IntStream ,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。

LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper)

返回一个 LongStream ,其中包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而产生的映射流的内容的结果。

void forEach(Consumer<? super T> action)

对此流的每个元素执行操作。

void forEachOrdered(Consumer<? super T> action)

如果流具有定义的遇到顺序,则以流的遇到顺序对该流的每个元素执行操作。

static <T> Stream<T> generate(Supplier<T> s)

返回无限顺序无序流,其中每个元素由提供的 Supplier 。

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

返回有序无限连续 Stream由函数的迭代应用产生 f至初始元素 seed ,产生 Stream包括 seed, f(seed) , f(f(seed)) ,等

Stream<T> limit(long maxSize)

返回由此流的元素组成的流,截短长度不能超过 maxSize 。

<R> Stream<R> map(Function<? super T,? extends R> mapper)

返回由给定函数应用于此流的元素的结果组成的流。

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)

返回一个 DoubleStream ,其中包含将给定函数应用于此流的元素的结果。

IntStream mapToInt(ToIntFunction<? super T> mapper)

返回一个 IntStream ,其中包含将给定函数应用于此流的元素的结果。

LongStream mapToLong(ToLongFunction<? super T> mapper)

返回一个 LongStream ,其中包含将给定函数应用于此流的元素的结果。

Optional<T> max(Comparator<? super T> comparator)

根据提供的 Comparator返回此流的最大元素。

Optional<T> min(Comparator<? super T> comparator)

根据提供的 Comparator返回此流的最小元素。

boolean noneMatch(Predicate<? super T> predicate)

返回此流的元素是否与提供的谓词匹配。

static <T> Stream<T> of(T... values)

返回其元素是指定值的顺序排序流。

static <T> Stream<T> of(T t)

返回包含单个元素的顺序 Stream 。

Stream<T> peek(Consumer<? super T> action)

返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。

Optional<T> reduce(BinaryOperator<T> accumulator)

使用 associative累积函数对此流的元素执行 reduction ,并返回描述减小值的 Optional (如果有)。

T reduce(T identity, BinaryOperator<T> accumulator)

使用提供的身份值和 associative累积功能对此流的元素执行 reduction ,并返回减小的值。

<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)

执行 reduction在此流中的元素,使用所提供的身份,积累和组合功能。

Stream<T> skip(long n)

在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。

Stream<T> sorted()

返回由此流的元素组成的流,根据自然顺序排序。

Stream<T> sorted(Comparator<? super T> comparator)

返回由该流的元素组成的流,根据提供的 Comparator进行排序。

Object[] toArray()

返回一个包含此流的元素的数组。

<A> A[] toArray(IntFunction<A[]> generator)

使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。 


三、Collectors

API:

Modifier and Type Method and Description
static <T> Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的双值函数的算术平均值。

static <T> Collector<T,?,Double> averagingInt(ToIntFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的整数值函数的算术平均值。

static <T> Collector<T,?,Double> averagingLong(ToLongFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的长值函数的算术平均值。

static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)

适应 Collector进行额外的整理转换。

static <T> Collector<T,?,Long> counting()

返回 Collector类型的接受元件 T计数输入元件的数量。

static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier)

返回 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素,并且在返回的结果 Map 。

static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)

返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。

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

返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。

static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier)

返回一个并发 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素。

static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)

返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。

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

返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。

static Collector<CharSequence,?,String> joining()

返回一个 Collector ,按照遇到的顺序将输入元素连接到一个 String中。

static Collector<CharSequence,?,String> joining(CharSequence delimiter)

返回一个 Collector ,按照遇到的顺序连接由指定的分隔符分隔的输入元素。

static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

返回一个 Collector ,它将按照指定的 Collector分隔的输入元素与指定的前缀和后缀进行连接。

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

适应一个 Collector类型的接受元件 U至类型的一个接受元件 T通过积累前应用映射函数到每个输入元素。

static <T> Collector<T,?,Optional<T>> maxBy(Comparator<? super T> comparator)

返回一个 Collector ,它根据给出的 Comparator产生最大元素,描述为 Optional<T> 。

static <T> Collector<T,?,Optional<T>> minBy(Comparator<? super T> comparator)

返回一个 Collector ,根据给出的 Comparator产生最小元素,描述为 Optional<T> 。

static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate)

返回一个 Collector ,根据Predicate对输入元素进行 Predicate ,并将它们组织成 Map<Boolean, List<T>> 。

static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream)

返回一个 Collector ,它根据Predicate对输入元素进行 Predicate ,根据另一个 Collector减少每个分区的值,并将其组织成 Map<Boolean, D> ,其值是下游缩减的结果。

static <T> Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op)

返回一个 Collector ,它在指定的 Collector下执行其输入元素的 BinaryOperator 。

static <T> Collector<T,?,T> reducing(T identity, BinaryOperator<T> op)

返回 Collector执行下一个指定的减少其输入元件的 BinaryOperator使用所提供的身份。

static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator<U> op)

返回一个 Collector ,它在指定的映射函数和 BinaryOperator下执行其输入元素的 BinaryOperator 。

static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)

返回一个 Collector , double生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。

static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)

返回一个 Collector , int生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。

static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)

返回一个 Collector , long生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。

static <T> Collector<T,?,Double> summingDouble(ToDoubleFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的双值函数的和。

static <T> Collector<T,?,Integer> summingInt(ToIntFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的整数值函数的和。

static <T> Collector<T,?,Long> summingLong(ToLongFunction<? super T> mapper)

返回一个 Collector ,它产生应用于输入元素的长值函数的和。

static <T,C extends Collection<T>>
Collector<T,?,C>
toCollection(Supplier<C> collectionFactory)

返回一个 Collector ,按照遇到的顺序将输入元素累加到一个新的 Collection中。

static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

返回一个并发的 Collector ,它将元素累加到 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。

static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)

返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将提供的映射函数应用于输入元素的结果。

static <T,K,U,M extends ConcurrentMap<K,U>>
Collector<T,?,M>
toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)

返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。

static <T> Collector<T,?,List<T>> toList()

返回一个 Collector ,它将输入元素 List到一个新的 List 。

static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。

static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)

返回一个 Collector ,它将元素累加到 Map ,其键和值是将提供的映射函数应用于输入元素的结果。

static <T,K,U,M extends Map<K,U>>
Collector<T,?,M>
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)

返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。

static <T> Collector<T,?,Set<T>> toSet()

返回一个 Collector ,将输入元素 Set到一个新的 Set 。 


工作中应用:

注:这个项目微服务架构使用dubbo

一、转换前数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  GeneTreeList  extends  ResponseBase {
     @XmlElements ({ @XmlElement (
     name =  "tree" ,
     type = GeneTree. class
)})
     private  List<GeneTree> treeList =  new  ArrayList();
 
     public  GeneTreeList() {
     }
 
     public  List<GeneTree> getTreeList() {
         return  this .treeList;
     }
 
     public  void  setTreeList(List<GeneTree> treeList) {
         this .treeList = treeList;
     }
}
 
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  GeneTree  extends  ResponseBase {
     @XmlAttribute
     private  int  portalId;
     @XmlAttribute
     private  int  parentTreeId;
     @XmlAttribute
     private  int  treeId;
     @XmlAttribute
     private  int  treeType;
     @XmlAttribute
     private  int  layer;
     @XmlAttribute
     private  int  order;
     private  String treeName;
     private  boolean  isLeaf;
     private  String template;
     private  int  retrieveId;
     private  int  filmCount;
     private  String icon =  "" ;
     private  String backgroundImg =  "" ;
     private  String cpid =  "" ;
     private  String copyright =  "" ;
     private  int  movieLimitCount;
     private  int  movieAuditCount;
     private  String moviePosterLimit =  "" ;
     private  Date updatetime;
     private  Date createtime;
     @XmlElements ({ @XmlElement (
     name =  "label" ,
     type = GeneTreeLabel. class
)})
     private  List<GeneTreeLabel> labels =  new  ArrayList();
 
     public  GeneTree() {
     }
//get/set方法
。。。。。。
}
 
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  GeneTreeLabel  implements  Serializable {
     @XmlAttribute
     private  int  typeId;
     @XmlAttribute
     private  String typeName =  "" ;
     @XmlAttribute
     private  int  labelId;
     @XmlAttribute
     private  String labelName =  "" ;
 
     public  GeneTreeLabel() {
     }
}

image.png

二、定义转换后数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  LabelList  extends  ResponseBase {
     @XmlElements ({ @XmlElement (
             name =  "Child" ,
             type = OutChild. class
     )})
     private  List<OutChild> childs =  new  ArrayList();
 
     public  LabelList(){}
 
     public  List<OutChild> getChilds() {
         return  childs;
     }
 
     public  void  setChilds(List<OutChild> childs) {
         this .childs = childs;
     }
}
 
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  OutChild  extends  ResponseBase {
     @XmlAttribute
     private  String typeName;
     @XmlAttribute
     private   int  typeId;
 
     @XmlElements ({ @XmlElement (
             name =  "label" ,
             type = OutLabel. class
     )})
     private  List<OutLabel> labels =  new  ArrayList();
     public  OutChild(){}
 
     public  List<OutLabel> getLabels() {
         return  labels;
     }
 
     public  void  setLabels(List<OutLabel> labels) {
         this .labels = labels;
     }
 
     public  void  setTypeName(String typeName) {
         this .typeName = typeName;
     }
 
     public  void  setTypeId( int  typeId) {
         this .typeId = typeId;
     }
 
     public  String getTypeName() {
 
         return  typeName;
     }
 
     public  int  getTypeId() {
         return  typeId;
     }
}
 
@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
public  class  OutLabel  extends  ResponseBase {
     @XmlAttribute
     private  int  labelId;
     @XmlAttribute
     private  String labelName;
 
     public  OutLabel(){}
 
     public  int  getLabelId() {
         return  labelId;
     }
 
     public  void  setLabelId( int  labelId) {
         this .labelId = labelId;
     }
 
     public  String getLabelName() {
         return  labelName;
     }
 
     public  void  setLabelName(String labelName) {
         this .labelName = labelName;
     }
}

image.png

三、处理逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
public  LabelList labellist(Integer epgid) {
     LabelList labelList =  new  LabelList();
 
     if  (epgid ==  null ) {
         labelList.setParamInvalidResponse( "epgId" , String.valueOf(epgid));
         return  labelList;
     }
     int  treeid =  0 ;
     boolean  opl =  true ;
     //geneTreeList-->labelList
     GeneTreeList geneTreeList = treeService.getTreeList(epgid, treeid, opl);
 
     if  ( null  == geneTreeList) {
         labelList.setNoDataResponse();
         return  labelList;
     }
 
     if  (geneTreeList.getTreeList().size() >  0 ) {
         ChangeIbsTreeList.change(labelList, geneTreeList);
         labelList.setSucessResponse(ResponseStatus.Source.None);
     else  {
         labelList.setNoDataResponse();
     }
     return  labelList;
}

下面代码中注释的是我写的逻辑,很原始的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
public  class  ChangeIbsTreeList {
//    private static boolean[] flag1 = new boolean[100];//以typeid为数组下标
 
     public  static  void  change(LabelList labellist, GeneTreeList geneTreeList) {
 
         List<GeneTreeLabel> geneTreeLabelList =  new  LinkedList<>();
 
 
         //获取所有的label
         for  (GeneTree geneTree : geneTreeList.getTreeList()) {
             geneTreeLabelList.addAll(geneTree.getLabels());
         }
         if  (geneTreeLabelList.size() ==  0 ) {
             return ;
         }
         //根据lableid和typeid生成不同的map
         //geneTreeLabelList.stream():可以用来获取流,参考:http://blog.csdn.net/u010425776/article/details/52344425  http://blog.csdn.net/u010425776/article/details/52346644
         //根据List创建Map:Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(p -> p, q->q*3));
         //Collectors.toMap(GeneTreeLabel::getLabelId, c -> c, (e1, e2) -> e1):
             //  GeneTreeLabel::getLabelId:是接收一个任务并产生一个只包含该任务标题的键的Function
             //   c -> c:一个用来返回任务本身的lambda表达式:http://www.importnew.com/16436.html   http://blog.csdn.net/u010425776/article/details/52334455
             //  (e1, e2) -> e1:处理重复问题
         Map<Integer, GeneTreeLabel> lableMap = geneTreeLabelList.stream().collect(Collectors.toMap(GeneTreeLabel::getLabelId, c -> c, (e1, e2) -> e1));
         Map<Integer, GeneTreeLabel> typeMap = geneTreeLabelList.stream().collect(Collectors.toMap(GeneTreeLabel::getTypeId, c -> c, (e1, e2) -> e1));
         //按type分类
         Map<Integer, List<GeneTreeLabel>> groupbyType =
                 geneTreeLabelList.stream().collect(groupingBy(GeneTreeLabel::getTypeId));
 
         //遍历生成Childs
         //t是integer类型
         //map是映射:将GeneTreeLabel转换成GeneTreeLabel.getTypeId()为int类型,然后去重
         //然后将int类型映射成函数需要的类型
         //注:第三行用到了得到的lableMap、typeMap、groupbyType
         List<OutChild> OutChilds =
                 (geneTreeLabelList.stream().map(GeneTreeLabel -> GeneTreeLabel.getTypeId()).distinct().collect(Collectors.toList()))
                         .stream().map(t -> GeneTreeLabel2OutChild(typeMap.get(t), groupbyType, lableMap)).collect(Collectors.toList());
 
 
         //遍历Childs,set Labels
         for  (OutChild child : OutChilds) {
             child.setLabels((groupbyType.get(child.getTypeId()).stream().map(GeneTreeLabel::getLabelId).distinct().collect(Collectors.toList())).stream().map(t -> GeneTreeLabel2OutLabel(lableMap.get(t))).collect(Collectors.toList()));
         }
         labellist.setChilds(OutChilds);
 
//        for (int i = 0; i < flag1.length; i++) {
//            flag1[i] = false;
//        }
//        List<GeneTree> treeList = geneTreeList.getTreeList();
//        List<OutChild> childList = new ArrayList<>();
//        getTreeList(treeList, childList);
//        labellist.setChilds(childList);
     }
 
     private  static  OutChild GeneTreeLabel2OutChild(GeneTreeLabel geneTreeLabel, Map<Integer, List<GeneTreeLabel>> groupbyType, Map<Integer, GeneTreeLabel> lableMap) {
         OutChild outChild =  new  OutChild();
         outChild.setTypeId(geneTreeLabel.getTypeId());
         outChild.setTypeName(geneTreeLabel.getTypeName());
 
         //List<OutLabel> labels = (groupbyType.get(geneTreeLabel.getTypeId()).stream().map(GeneTreeLabel -> GeneTreeLabel.getLabelId()).distinct().collect(Collectors.toList())).stream().map(t -> GeneTreeLabel2OutLabel(lableMap.get(t))).collect(Collectors.toList());
 
         //OutChild.setLabels(null);
         return  outChild;
     }
 
     private  static  OutLabel GeneTreeLabel2OutLabel(GeneTreeLabel geneTreeLabel) {
         OutLabel outLabel =  new  OutLabel();
         outLabel.setLabelId(geneTreeLabel.getLabelId());
         outLabel.setLabelName(geneTreeLabel.getLabelName());
         return  outLabel;
     }
 
//    public static void getTreeList(List<GeneTree> treeList, List<OutChild> childList) {
//
//        Iterator<GeneTree> it = treeList.iterator();
//        while (it.hasNext()) {
//            GeneTree geneTree = it.next();
//            List<GeneTreeLabel> labels = geneTree.getLabels();
//            setLabels(labels, childList);
//        }
//    }
//
//    public static void setLabels(List<GeneTreeLabel> labels, List<OutChild> childList) {
//        Iterator<GeneTreeLabel> it = labels.iterator();
//        while (it.hasNext()) {
//            GeneTreeLabel label = it.next();
//
//            if (false == flag1[label.getTypeId()]) {//如果标志为false,说明child不存在
//                OutChild outChild = new OutChild();
//                outChild.setTypeId(label.getTypeId());
//                outChild.setTypeName(label.getTypeName());
//
//                List<OutLabel> outLabellist = new ArrayList<>();
//                OutLabel outLabel = new OutLabel();
//                outLabel.setLabelId(label.getLabelId());
//                outLabel.setLabelName(label.getLabelName());
//                outLabellist.add(outLabel);
//
//                outChild.setLabels(outLabellist);
//
//                childList.add(outChild);
//
//                flag1[label.getTypeId()] = true;
//            } else {                                 //否则已经建立这个类型的child,然后遍历child集合,找到对应的child
//                Iterator<OutChild> it1 = childList.iterator();
//                while (it1.hasNext()) {
//                    OutChild outChild = it1.next();
//                    if (outChild.getTypeId() == label.getTypeId()) {//找到对应的child,然后查找child里面的label是否重复
//                        List<OutLabel> outLabels = outChild.getLabels();
//                        Iterator<OutLabel> it2 = outLabels.iterator();
//                        int i = 0;
//                        while (it2.hasNext()) {//遍历得到label
//                            OutLabel outLabel = it2.next();
//                            if (outLabel.getLabelId() == label.getLabelId()) {
//                                break;
//                            }
//                            i = i + 1;
//                        }
//                        if (i >= outLabels.size()) {
//                            OutLabel outLabel = new OutLabel();
//                            outLabel.setLabelId(label.getLabelId());
//                            outLabel.setLabelName(label.getLabelName());
//                            outLabels.add(outLabel);
//
//                            outChild.setLabels(outLabels);
//                        }
//                    }
//                }
//            }
//        }
//    }
}