Java8新特性--Stream流的特性

package stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamDemo {

    public static void main(String[] args) {

        System.out.println("-------------Stream对象的构建----------------");
        /**
         * 1. Stream对象的构建
         */
        // 1. Stream的构建
        // 看底层源码, Stream.of 用的是 Arrays.stream(values); 来构建,因此可以用Arrays进行构建
        Stream<String> stream01 = Stream.of("a", "b", "c");
        // 2. Arrays 用数组构建
        String[] strArr = new String[]{"a", "b", "c"};
        Stream<String> stream03 = Stream.of(strArr);
        Stream<String> stream02 = Arrays.stream(strArr);
        // 3. 利用集合进行构建, 先创建一个集合,在从集合转换成Stream
        // Arrays.asList  就是把数据变成集合
        List<String> list = Arrays.asList(strArr);
        Stream<String> stream04 = list.stream();

        /**
         * 对于基本数值类型,有以下几种Stream流:Stream, IntStream, LongStream, DoubleStream
         * 当然我们也可以用Stream<Integer> Stream<Long>  Stream<Double>
         * 但是自动装箱拆箱会很耗时,所以特别为这三种Stream提供了特定的Stream
         * Java8 中还没提供其他数据类型的Stream
         */

        System.out.println("-------------Stream的基本类型对象的构建----------------");
        /**
         * 2. 数值Stream的创建
         */
        // 1. 使用IntStream.of
        IntStream intStream = IntStream.of(new int[]{1, 2, 3});
        // 2. 使用数组创建
        IntStream intStream1 = Arrays.stream(new int[]{1, 2, 3});
        // 3. 使用rang方法创建, [1, 3)
        IntStream intStream2 = IntStream.range(1, 3);
        // 4. 使用rangClose 创建 [1, 3]
        IntStream intStream3 = IntStream.rangeClosed(1, 3);

        System.out.println("-------------Stream对象转其他类型----------------");
        /**
         * 3. Stream 转其他类型
         */
        Stream<Integer> stream = Stream.of(new Integer[]{1, 2, 3});
        // 1. stream 转数组
        Integer[] intArr = stream.toArray(Integer[]::new);
        // 2. stream 转集合
        List<Integer> list1 = stream.collect(Collectors.toList());
        List<Integer> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
        Set<Integer> set = stream.collect(Collectors.toSet());
        Set<Integer> set1 = stream.collect(Collectors.toCollection(HashSet::new));
        // 3. stream 转为joining
        Stream<String> stream1 = Stream.of(new String[]{"1", "b", "c"});
        String str1 = stream1.collect(Collectors.joining()).toString();

        /**
         * 注意:一个Stream只可以被抛出一次,而上面的代码为了简洁重复了多次
         * 上面的代码直接运行会抛出异常:java.lang.IllegalStateException   违反规定异常
         */

        /**
         * Stream操作:当把数据接口包装成stream后,就可以对stream进行各种操作了
         *
         * Intermediate: 中间操作
         * map(mapToInt, faltMap), filter, distinct(去除重复列), sorted(排序), peek, limit, skip, parallel, sequential, unordered
         * Short-circuiting:  短路操作
         * anyMatch, allMatch, noneMatch, findFirst, findAny, limit
         *
         */

        // map, flatMap映射:把stream的元素映射成另一个元素。
        /**
         * 1. 将字符串数组中所有的字符 转成大写
         */
        String[] str2 = new String[]{"abc", "hello", "keep", "Time"};
        Stream<String> stream2 = Stream.of(str2);
        // map是映射操作,collect是对这些数据进行收集,并且返回相应的集合
        List<String> list3 = stream2.
                map(String::toUpperCase).
                collect(Collectors.toList());
        System.out.println(list3.toString());

        /**
         * Stream操作:当把数据接口包装成stream后,就可以对stream进行各种操作了
         *
         * Intermediate: 中间操作
         * map(mapToInt, faltMap), filter, distinct(去除重复列), sorted(排序), peek, limit, skip, parallel, sequential, unordered
         * Short-circuiting:  短路操作
         * anyMatch, allMatch, noneMatch, findFirst, findAny, limit
         *
         */

        // map, flatMap映射:把stream的元素映射成另一个元素。
        /**
         * 1. 将字符串数组中所有的字符 转成大写
         */
        String[] str2 = new String[]{"abc", "hello", "keep", "Time"};
        Stream<String> stream2 = Stream.of(str2);
        // map是映射操作,collect是对这些数据进行收集,并且返回相应的集合
        List<String> list3 = stream2.
                map(String::toUpperCase).
                collect(Collectors.toList());
        System.out.println(list3.toString());

        System.out.println("-------for-Each循环-------");
        // 对于stream流,可以对其进行forEach循环操作
        // 此处我犯了一个错误,一个Stream流只能用一次,因此要重新创建一个stream流
        Stream<String> stream = Stream.of(str2);
        stream.
                map(s -> s.toUpperCase()).
                collect(Collectors.toList()).
                forEach(s -> System.out.println(s));
        // 如果对stream进行操作一般不会创建一个stream对象,而是使用List.stream();   集合
        // 2. 对Integer的集合进行平方操作
        Integer[] init = new Integer[]{1, 2, 3, 4, 5};
        List<Integer> list = Arrays.asList(init);
        list.stream().
                map(i -> i * i).
                forEach(i -> System.out.println(i));

        System.out.println("--------------flatMap的用法----------------");
        /**
         * 3. map生成的是1:1关系,而flatMap 对应的是1:N 关系
         * map:  <R> Stream<R> map(Function<? super T, ? extends R> mapper);
         * flatMap: <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
         */
        Stream<List<Integer>> stream1 = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
        Stream<Integer> stream3 = stream1.flatMap(e -> e.stream());
        stream3.forEach(i -> System.out.println(i + 1));

        /**
         * forEach 方法:带入参数,然后不返回任何参数。
         */
        System.out.println("------测试flatMap----------");
        // 将字符串 tom.Li lucy.Liu 用'.' 作为分割,返回4个字符串
        Stream<String> stream4 = Stream.of("tom.Li", "lucy.Liu");
        Stream<String> stream5 = stream4.flatMap(e -> Stream.of(e.split("[.]")));
        stream5.forEach(System.out::println);

        /**
         * filter: 对Stream进行筛选,筛选下来的元素生成一个新的Stream
         *     通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,
         *     所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach, 比如collect操作)。
         *     forEach需要一个函数来对过滤后的元素依次执行。
         *     forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作
         */
        System.out.println("---------filter方法的使用-------------------");
        List<String> list1 = Arrays.asList("Hi", "Hello", "Sea", "Sun", "TomAndSally");
        Stream<String> stream6 = list1.stream().filter(s -> s.length() > 3);
        // 这里我筛选出字符串长度 > 3 的数据,返回一个集合
        List<String> list2 = list1.stream().filter(s -> s.length() > 3).collect(Collectors.toList());
        System.out.println("List2 = " + list2.toString());
        stream6.forEach(System.out::println);
        System.out.println("-------------peek的用法---------------");
        /**
         * 发现了一个规律,peek和filter的筛选不是
         */
        List<String> list4 = list1.stream().
                filter(e -> e.length() > 2).
                peek(s -> System.out.println("长度大于2 的字符串为:" + s)).
                filter(e -> e.length() > 3).
                peek(s -> System.out.println("长度大于3的字符串为:" + s)).
                collect(Collectors.toList());
        System.out.println("peek的用法: " + list4.toString());

        /**
         * findFirst:  返回stream流中的第一个元素,返回值类型Optional
         */
        System.out.println("---------findFirst的用法-----------------");
        List<String> list5 = Arrays.asList("ab", "cde");
        Optional<String> first = list5.stream().findFirst();
        System.out.println(first.orElse("该集合为空"));

        /**
         * sort排序:排序是一个中间操作,返回的是排序好后的stream操作。如果你不能制定一个自定义的排序,那么就会使用默认排序
         * 它比数组的排序更强的作用是,你在排序前对Stream进行 map, flatMap, filter, limit, distinct, skip来减少元素数量
         * 筛选后进行排序能够大大的缩短执行时间
         */
        System.out.println("---------sorted排序----------------");
        List<String> list6 = Arrays.asList("test", "hello", "world", "java", "tom", "C", "javascript");
        // 1. 按照默认进行排序
        // 默认排序是按照首字母大小从小往大排序
        Stream<String> stream7 = list6.stream().sorted();
        stream7.forEach(System.out::println);
        // 2. 按照字符串长度进行排序
        // sorted调用的是compare函数,compare返回一个int类型的值
        // 如果长度相同,就按照集合中原先的顺序来
        System.out.println("--------------------------");
        list6.stream().sorted((s1, s2) -> s1.length() - s2.length()).forEach(System.out::println);
        // 3. 先筛选出字符串中有t的,然后按照长度大小排序
        System.out.println("-----sorted3---------------");
        list6.stream().filter(s -> s.startsWith("t")).sorted((s1, s2) -> s1.length() - s2.length()).forEach(System.out::println);

        /**
         * Match 匹配:match 提供了多种匹配操作,   allMatch  所有的元素都通过, anyMatch  只要有一个通过,  noneMatch 一个都不通过
         *  所有的匹配都是最终操作,并且返回一个Boolean类型的值。
         */
        System.out.println("----------Match匹配--------------");
        // 如果list的集合所有的string字符串都有t, 那么返回true
        boolean isAllmatch = list6.stream().allMatch(s -> s.startsWith("t"));
        System.out.println("isAllmatch = " + isAllmatch);

        // 2. anyMatch:只要有一个数据成立,就返回true
        boolean anyMatch = list6.stream().anyMatch(s -> s.length() > 5);
        System.out.println("anyMatch = " + anyMatch);

        // 3. noneMatch: 全都不成立,就返回true
        boolean noneMatch = list6.stream().noneMatch(s -> s.isEmpty());
        System.out.println("noneMatch = " + noneMatch);

        /**
         * count:计数是一个最终操作,返回Stream中元素的个数。返回值类型是long
         */
        // 返回list6集合中,字符串长度大于3的字符串个数
        System.out.println("----------count------------");
        long count = list6.stream().filter(s -> s.length() > 3).count();
        System.out.println(count);

        /**
         * 规约合并reduce
         * 这是一个最终操作,允许通过制定的函数来将stream中的多个元素规约合并成一个元素
         * 它提供了一个起始值,然后按照运算规则,和前面的Stream的第一个,第二个,第n个元素组合
         * 常用的方法有average,sum,min,max,and,count,返回单个的结果值
         * 并且reduce操作每处理一个元素总是创建一个新值
         */
        System.out.println("-----------------reduce----------------");
        // 比如stream的sum就相当于
        // [1, 10)
        IntStream intStream = IntStream.range(1, 10);
        IntStream intStream1 = IntStream.range(1, 10);
        // 转换成,
        Integer sum1 = intStream.reduce(5, (a, b) -> (a + b));
        // 或者
        Integer sum2 = intStream1.reduce(1, Integer::sum);
        // 起始值:start + a + b
        System.out.println("返回结果为起始值为5sum1 = " + sum1 + ";或者起始值1sum2 = " + sum2);

        // 也有没有起始值的情况,这时候会把stream的前面两个元素组合起来,返回的是optional, 比如min, max
        IntStream intStream2 = IntStream.range(1, 10);
        OptionalInt optionalInt = intStream2.reduce((a, b) -> a < b ? a : b);
        // max
        IntStream intStream3 = IntStream.range(1, 10);
        OptionalInt optionalInt1 = intStream3.reduce((a, b) -> a > b ? a : b);

        // 对于reduce来说,有起始值会返回相应的对应类型,如果没有起始值,会返回一个Optional<U> 的类型
        // 比如:contact字符串连接
        String str = Stream.of("a", "b", "c", "d").reduce("", String::concat);
        System.out.println(str);
        Optional<String> optionalS = Stream.of("a", "b", "c", "d").reduce(String::concat);

        // 写一个reduce的模板
        Optional<String> optionalS1 = list6.stream().
                sorted((s1, s2) -> s1.length() - s2.length()).
                filter(s -> s.startsWith("t")).
                map(s -> s + "perper").
                reduce((s1, s2) -> s1 + " | " + s2);
        /**
         * 1. 先创建一个steam流对象
         * 2. 然后将流对象中筛选出首字母为 t 的
         * 3. 将筛选出来的stream,每个数据在字母最后加上 + "perper"
         * 4. 将所有的数据,用 | 规约合并起来
         */
        System.out.println(optionalS1.get());

        /**
         * limit, skip
         * limit:得到前n个元素
         * skip:跳过前n个元素
         */
        List<String> list7 = Arrays.asList("test","javap","hello","world","java","tom","C","javascript");
        // limit 选择前五个元素    "test","javap","hello","world","java"
        Stream<String> stream8 = list7.stream().limit(5);
        // skip 跳过前五个元素     "tom","C","javascript"
        Stream<String> stream9 = list7.stream().skip(5);

        /**
         * Collector 收集元素, 辅助进行各类有用的操作
         * 例如把stream转变为Collection, 或者把Stream 元素进行分组
         */
        List<String> list8 = Arrays.asList("test","hello","world","java","tom","C","javascript");
        List<String> result = list8.stream().filter(s -> s.startsWith("t")).collect(Collectors.toList());

        System.out.println("------按照字符串长度进行分组------------");
        // 按照字符串的长度进行分组
        Map<Integer, List<String>> collect = list8.stream().collect(Collectors.groupingBy(s -> s.length()));
        System.out.println(collect.toString());

        /**
         * 并行和串行stream
         */
        // 生成100万个不同的字符串放到集合中去
        int max = 1000000;
        List<String> values = new ArrayList<String>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }

        System.out.println("-----查看并行时间------------");
        // 1纳秒 * 10^9 = 1秒
        long t0 = System.nanoTime();
        // 串行stream     串行时间:832311645
        //long count1 = values.stream().sorted().count();
        // 并行stream     并行时间:474983692      时间减少了近2倍
        long count2 = values.parallelStream().sorted().count();

        // 结束时间:t1
        long t1 = System.nanoTime();

        long time = t1 - t0;
        System.out.println(count2);
        System.out.println(time);

    }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 支持向量机非线性回归通用MATLAB程序解析 #### 一、概述 本文将详细介绍一个基于MATLAB的支持向量机(SVM)非线性回归的通用程序。该程序采用支持向量机方法来实现数据的非线性回归,并通过不同的核函数设置来适应不同类型的数据分布。此外,该程序还提供了数据预处理的方法,使得用户能够更加方便地应用此程序解决实际问题。 #### 二、核心功能与原理 ##### 1. 支持向量机(SVM) 支持向量机是一种监督学习模型,主要用于分类和回归分析。对于非线性回归任务,SVM通过引入核技巧(kernel trick)将原始低维空间中的非线性问题转换为高维空间中的线性问题,从而实现有效的非线性建模。 ##### 2. 核函数 核函数的选择直接影响到模型的性能。本程序内置了三种常用的核函数: - **线性核函数**:`K(x, y) = x'y` - **多项式核函数**:`K(x, y) = (x'y + 1)^d` - **径向基函数(RBF)**:`K(x, y) = exp(-γ|x - y|^2)` 其中RBF核函数被广泛应用于非线性问题中,因为它可以处理非常复杂的非线性关系。本程序默认使用的是RBF核函数,参数`D`用于控制高斯核函数的宽度。 ##### 3. 数据预处理 虽然程序本身没有直接涉及数据预处理的过程,但在实际应用中,对数据进行适当的预处理是非常重要的。常见的预处理步骤包括归一化、缺失值处理等。 ##### 4. 模型参数 - **Epsilon**: ε-insensitive loss function的ε值,控制回归带宽。 - **C**: 松弛变量的惩罚系数,控制模型复杂度与过拟合的风险之间的平衡。 #### 三、程序实现细节 ##### 1. 函数输入与输出 - **输入**: - `X`: 输入特征矩阵,维度为(n, l),其中n是特征数量,l是样本数量。 - `Y`: 目标值向量,长度为l。 - `Epsilon`: 回归带宽。 - `C`: 松弛变量的惩罚系数。 - `D`: RBF核函数的参数。 - **输出**: - `Alpha1`: 正的拉格朗日乘子向量。 - `Alpha2`: 负的拉格朗日乘子向量。 - `Alpha`: 拉格朗日乘子向量。 - `Flag`: 标记向量,表示每个样本的类型。 - `B`: 偏置项。 ##### 2. 核心代码解析 程序首先计算所有样本间的核矩阵`K`,然后构建二次规划问题并求解得到拉格朗日乘子向量。根据拉格朗日乘子的值确定支持向量,并计算偏置项`B`。 - **核矩阵计算**:采用RBF核函数,通过`exp(-(sum((xi-xj).^2)/D))`计算任意两个样本之间的相似度。 - **二次规划**:构建目标函数和约束条件,使用`quadprog`函数求解最小化问题。 - **支持向量识别**:根据拉格朗日乘子的大小判断每个样本是否为支持向量,并据此计算偏置项`B`。 #### 四、程序扩展与优化 - **多核函数支持**:可以通过增加更多的核函数选项,提高程序的灵活性。 - **自动调参**:实现参数自动选择的功能,例如通过交叉验证选择最优的`Epsilon`和`C`值。 - **并行计算**:利用MATLAB的并行计算工具箱加速计算过程,特别是当样本量很大时。 #### 五、应用场景 该程序适用于需要进行非线性回归预测的场景,如经济预测、天气预报等领域。通过调整核函数和参数,可以有效应对各种类型的非线性问题。 ### 总结 本程序提供了一个支持向量机非线性回归的完整实现框架,通过灵活的核函数设置和参数调整,能够有效地处理非线性问题。对于需要进行回归预测的应用场景,这是一个非常实用且强大的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值