一、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  Optional empty()

返回一个空的 Optional实例。

boolean equals(Object obj)

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

Optional filter(Predicate predicate)

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

 Optional flatMap(Function> mapper)

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

T get()

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

int hashCode()

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

void ifPresent(Consumer consumer)

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

boolean isPresent()

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

 Optional map(Function mapper)

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

static  Optional of(T value)

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

static  Optional ofNullable(T value)

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

T orElse(T other)

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

T orElseGet(Supplier other)

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


T
orElseThrow(Supplier 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 predicate)

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

boolean anyMatch(Predicate predicate)

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

static  Stream.Builder builder()

返回一个 Stream的构建器。

 R collect(Collector collector)

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

 R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)

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

static  Stream concat(Stream a, Stream b)

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

long count()

返回此流中的元素数。

Stream distinct()

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

static  Stream empty()

返回一个空的顺序 Stream

Stream filter(Predicate predicate)

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

Optional findAny()

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

Optional findFirst()

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

 Stream flatMap(Function> mapper)

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

DoubleStream flatMapToDouble(Function mapper)

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

IntStream flatMapToInt(Function mapper)

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

LongStream flatMapToLong(Function mapper)

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

void forEach(Consumer action)

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

void forEachOrdered(Consumer action)

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

static  Stream generate(Supplier s)

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

static  Stream iterate(T seed, UnaryOperator f)

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

Stream limit(long maxSize)

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

 Stream map(Function mapper)

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

DoubleStream mapToDouble(ToDoubleFunction mapper)

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

IntStream mapToInt(ToIntFunction mapper)

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

LongStream mapToLong(ToLongFunction mapper)

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

Optional max(Comparator comparator)

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

Optional min(Comparator comparator)

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

boolean noneMatch(Predicate predicate)

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

static  Stream of(T... values)

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

static  Stream of(T t)

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

Stream peek(Consumer action)

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

Optional reduce(BinaryOperator accumulator)

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

T reduce(T identity, BinaryOperator accumulator)

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

 U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)

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

Stream skip(long n)

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

Stream sorted()

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

Stream sorted(Comparator comparator)

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

Object[] toArray()

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

 A[] toArray(IntFunction generator)

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


三、Collectors

API:

Modifier and Type Method and Description
static  Collector averagingDouble(ToDoubleFunction mapper)

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

static  Collector averagingInt(ToIntFunction mapper)

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

static  Collector averagingLong(ToLongFunction mapper)

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

static  Collector collectingAndThen(Collector downstream, Function finisher)

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

static  Collector counting()

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

static  Collector>> groupingBy(Function classifier)

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

static  Collector> groupingBy(Function classifier, Collector downstream)

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

static >
Collector
groupingBy(Function classifier, Supplier mapFactory, Collector downstream)

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

static  Collector>> groupingByConcurrent(Function classifier)

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

static  Collector> groupingByConcurrent(Function classifier, Collector downstream)

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

static >
Collector
groupingByConcurrent(Function classifier, Supplier mapFactory, Collector downstream)

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

static Collector joining()

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

static Collector joining(CharSequence delimiter)

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

static Collector joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

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

static  Collector mapping(Function mapper, Collector downstream)

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

static  Collector> maxBy(Comparator comparator)

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

static  Collector> minBy(Comparator comparator)

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

static  Collector>> partitioningBy(Predicate predicate)

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

static  Collector> partitioningBy(Predicate predicate, Collector downstream)

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

static  Collector> reducing(BinaryOperator op)

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

static  Collector reducing(T identity, BinaryOperator op)

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

static  Collector reducing(U identity, Function mapper, BinaryOperator op)

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

static  Collector summarizingDouble(ToDoubleFunction mapper)

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

static  Collector summarizingInt(ToIntFunction mapper)

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

static  Collector summarizingLong(ToLongFunction mapper)

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

static  Collector summingDouble(ToDoubleFunction mapper)

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

static  Collector summingInt(ToIntFunction mapper)

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

static  Collector summingLong(ToLongFunction mapper)

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

static >
Collector
toCollection(Supplier collectionFactory)

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

static  Collector> toConcurrentMap(Function keyMapper, Function valueMapper)

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

static  Collector> toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)

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

static >
Collector
toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier)

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

static  Collector> toList()

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

static  Collector> toMap(Function keyMapper, Function valueMapper)

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

static  Collector> toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)

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

static >
Collector
toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier)

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

static  Collector> toSet()

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


工作中应用:

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

一、转换前数据结构

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class GeneTreeList extends ResponseBase {
    @XmlElements({@XmlElement(
    name = "tree",
    type = GeneTree.class
)})
    private List treeList = new ArrayList();

    public GeneTreeList() {
    }

    public List getTreeList() {
        return this.treeList;
    }

    public void setTreeList(List 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 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() {
    }
}

Java8新特性-官方库新特性_第1张图片

二、定义转换后数据结构

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class LabelList extends ResponseBase {
    @XmlElements({@XmlElement(
            name = "Child",
            type = OutChild.class
    )})
    private List childs = new ArrayList();

    public LabelList(){}

    public List getChilds() {
        return childs;
    }

    public void setChilds(List 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 labels = new ArrayList();
    public OutChild(){}

    public List getLabels() {
        return labels;
    }

    public void setLabels(List 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;
    }
}

Java8新特性-官方库新特性_第2张图片

三、处理逻辑

@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.setSuce***esponse(ResponseStatus.Source.None);
    } else {
        labelList.setNoDataResponse();
    }
    return labelList;
}

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

public class ChangeIbsTreeList {
//    private static boolean[] flag1 = new boolean[100];//以typeid为数组下标

    public static void change(LabelList labellist, GeneTreeList geneTreeList) {

        List 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 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 lableMap = geneTreeLabelList.stream().collect(Collectors.toMap(GeneTreeLabel::getLabelId, c -> c, (e1, e2) -> e1));
        Map typeMap = geneTreeLabelList.stream().collect(Collectors.toMap(GeneTreeLabel::getTypeId, c -> c, (e1, e2) -> e1));
        //按type分类
        Map> groupbyType =
                geneTreeLabelList.stream().collect(groupingBy(GeneTreeLabel::getTypeId));

        //遍历生成Childs
		//t是integer类型
		//map是映射:将GeneTreeLabel转换成GeneTreeLabel.getTypeId()为int类型,然后去重
		//然后将int类型映射成函数需要的类型
		//注:第三行用到了得到的lableMap、typeMap、groupbyType
        List 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 treeList = geneTreeList.getTreeList();
//        List childList = new ArrayList<>();
//        getTreeList(treeList, childList);
//        labellist.setChilds(childList);
    }

    private static OutChild GeneTreeLabel2OutChild(GeneTreeLabel geneTreeLabel, Map> groupbyType, Map lableMap) {
        OutChild outChild = new OutChild();
        outChild.setTypeId(geneTreeLabel.getTypeId());
        outChild.setTypeName(geneTreeLabel.getTypeName());

        //List 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 treeList, List childList) {
//
//        Iterator it = treeList.iterator();
//        while (it.hasNext()) {
//            GeneTree geneTree = it.next();
//            List labels = geneTree.getLabels();
//            setLabels(labels, childList);
//        }
//    }
//
//    public static void setLabels(List labels, List childList) {
//        Iterator 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 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 it1 = childList.iterator();
//                while (it1.hasNext()) {
//                    OutChild outChild = it1.next();
//                    if (outChild.getTypeId() == label.getTypeId()) {//找到对应的child,然后查找child里面的label是否重复
//                        List outLabels = outChild.getLabels();
//                        Iterator 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);
//                        }
//                    }
//                }
//            }
//        }
//    }
}