乐趣区

关于java:Java基础16不可变集合Stream流和异常

1. 不可变汇合

不能够扭转的汇合,在整个应用的生命周期中,自创立后汇合就不变,尝试批改会报错
。实现的起因,更好的进攻和被不信赖库调用时,不可变的模式会更平安。

1.1 创立

在 List、Set 和 Map 这些接口中都提供了静态方法 of 来进行创立,创立出的汇合不可修
改、新增和删除。

public class Demo {public static void main(String[] args) {
        // 创立不可变 List
        List<Integer> lisOf = List.of(1, 2, 3, 4);
        // 只能够获取,不能够删,改和增
        System.out.println(lisOf.get(0));

        // 2、不可变的 Set 汇合,jdk 版本须要高于 8
        // Set<String> names = Set.of("迪丽热巴", "迪丽热九", "马尔扎哈", "卡尔眨巴");
        // names.add("三少爷");
        // System.out.println(names);

        // 3、不可变的 Map 汇合,jdk 版本须要高于 8
        // Map<String, Integer> maps = Map.of("huawei",2, "Java 开发", 1 , "手表", 1);
        // maps.put("衣服", 3);
        // System.out.println(maps);

    }
}

2. Stream 流

在 JDK8 之后,得益于 Lambda 表达式的函数式编程,引入了 Stream 流。它简化了汇合
和数值的操作。

// 示例
public class StreamTest {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "李小龙", "成龙", "李连杰", "李莲英", "叶问", "沈腾");

        // 传统办法
        System.out.println("传统办法");
        for (int i = 0; i < arrayList.size(); i++) {String s = arrayList.get(i);
            if (s.startsWith("李") && s.length() >= 3) {System.out.println(s);
            }
        }

        // Stream 流办法
        System.out.println("Stream 流形式");
        Stream<String> stream = arrayList.stream();
        stream.filter(s -> s.startsWith("李")).filter(s -> s.length() >= 3).forEach(s -> System.out.println(s));
    }
}

2.1 Stream 流的创立

流在应用过胜利,总共有三个阶段:

  • 取得流:取得操作汇合和数值的 ’ 流水线 ’
  • 两头操作:相似 ’ 流水线 ’ 上的操作,操作之后还能够持续前面的操作
  • 终结办法:一个流水线只有一个终结办法,此办法一旦执行,流水线就会进行。

2.1.1 取得 Stream 流

取得数组和汇合的 Stream 流

  1. 取得汇合流

    // 在汇合中 Collection 默认办法,此办法 1.8 之后退出
    default Stream<E> stream()
public class StreamDemo1 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();
        HashSet<String> set = new HashSet<>();
        HashMap<Object, Object> map = new HashMap<>();
        
        // 取得汇合 Stream 流
        Stream<String> stream = list.stream();
        Stream<String> stream1 = set.stream();
        Stream<Object> stream2 = map.keySet().stream();
        Stream<Object> stream3 = map.values().stream();
    }
}
  1. 取得数组流

    public class StreamDemo2 {public static void main(String[] args) {String[] str = {"张三", "李四", "王二"};
    
         // 取得数组流
         Stream<String> stream1 = Arrays.stream(str);
         Stream<String> stream2 = Stream.of("张三", "李四", "王二");
     }
    }

2.1.2 两头操作

// 罕用办法

// 去除流中反复元素
Stream<T> distinct()
// 获取流前指定元素
Stream<T> limit(long maxSize)
// 跳过指定元素
Stream<T> skip(long n)
// 过滤流指定数据
Stream<T> filter(Predicate<? super T> predicate)
// 合并两个流
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
// 对流进行加工 
<R> Stream<R> map(Function<? super T,? extends R> mapper)
// 示例
public class StreamDemo3 {public static void main(String[] args) {
        // 创立数组
        Integer[] x = {0, 1, 3, 5, 7, 9, 11}, y = {9, 2, 4, 6, 8};

        // 创立数组流
        Stream<Integer> x1 = Stream.of(x);
        Stream<Integer> y1 = Stream.of(y);

        Stream<Integer> concat = Stream.concat(x1, y1);
        // 跳过前 4 个、取前 6 个、过滤数值大于等于 5、去重和后果值乘 10,而后打印流内容完结
        concat.skip(4).limit(6)
                .filter(i -> i >= 5)
                .distinct()
                .map(i -> i * 10)
                .forEach(i -> System.out.println(i));
    }
}
  • 以上办法为非终结办法,操作流后不会被敞开,流反对链式编程
  • 在 Stream 流中无奈批改汇合或者数组数据,然而能够通过相似 map 办法进行加工

2.1.3 终结办法

能够通过终结办法终结流的操作,非终结办法能够持续链式操作,终结办法不反对。

// 罕用办法

// 循环流元素
void forEach(Consumer<? super T> action)
// 统计流大小
long count()

2.1.4 Stream 流数据收集

一些操作后须要取得流中数据,转换成汇合或数组。

// 罕用办法

// 转换成数组
<A> A[] toArray(IntFunction<A[]> generator)
// 转换成汇合 
<R,A> R collect(Collector<? super T,A,R> collector)
public class StreamDemo3 {public static void main(String[] args) {
        // 创立数组
        Integer[] x = {0, 1, 3, 5, 7, 9, 11, 9, 2, 4, 6, 8};

        // 取得流
        Stream<Integer> stream = Arrays.stream(x);
        // 流转换成 List 汇合
        List<Integer> list = stream.filter(i -> i >= 5).collect(Collectors.toList());
        // 流转换成 Set 汇合
        Set<Integer> set = stream.collect(Collectors.toSet());
        // 流转换成数组
        Integer[] array = stream.toArray(value -> new Integer[0]);
    }
}

3. 异样

异样是程序在 ’ 执行 ’ 或 ’ 编译 ’ 期呈现的问题,比方越界和空指针问题。一旦出现异常
jvm 就会退出执行,所有要提前解决异样,减少程序健壮性和安全性。

3.1 异样体系

异样体系次要如下:

  1. Error:零碎级别异样,代码无序管制
  2. Excrption:

    • RuntimeException 及其子类:运行时异样,编译时不会。
    • 除以上异样:编译时异样,必须解决否则程序编译不通过,程序无奈进行运行

程序编写在后缀为 java 的文件中 -> 应用 javac 命令编译文件成 class(有编译异
常此时将不会通过)-> 应用 java 命令运行字节码文件(如果程序有运行时异样将
终止程序报错)-> 运行完结

3.2 异样解决

3.2.1 零碎默认解决

  1. 程序会在出现异常的中央,默认创立一个异样对象:ArithmeticException
  2. 从出现异常的地点将异样抛给调用者,调用者抛给 jvm 虚拟机
  3. 虚拟机在接管到异样后,将在管制台上显示异样信息
  4. 从出现异常地点将程序终止

这种解决是被动的,出现异常程序就完结。

3.2.2 手动解决

3.2.2.1 throws

此种办法是把可能呈现的异样抛给调用者

// 格局一
修饰符 返回值 办法(形参列表) throws 异样类名{
}

// 格局二 
throw new 异样类名(实参);

3.2.2.1 try…catch…

此种办法是捕捉可能呈现的异样,如果出现异常,程序猿能够本人解决。

// 格局一
try{...} catch (异样类 变量名) {...}

// 格局二
try{...} catch (异样类 变量名 1) {...} catch (异样类 变量名 2) {...}

// 格局二
try{...} catch (异样类 变量名 1) {...} finally {...}
public class TrcatchTest {public static void main(String[] args) {
        try {int x = 1 / 0;} catch (Exception e) {
            // 取得异样信息
           System.out.println("异样信息:" + e.getMessage());
           // 解决异样代码
        }
        System.out.println("持续前面的的操作...");
    }
}

public class TrcatchTest1 {public static void main(String[] args) {
      try {int x = 1 / 0;} catch (Exception e) {
         // 取得异样信息
         System.out.println("异样信息:" + e.getMessage());
         // 解决异样代码
      }finally {System.out.println("这个程序始终会执行");
      }
      System.out.println("持续前面的的操作...");
   }
}

3.2.2.2 混合双打

可本人抛出异样,而后本人捕捉异样解决。这样就能够个体解决异样。

// 示例
public class TrcatchTest2 {public static void main(String[] args) {
      try {exceptionTest();
      } catch (Exception e) {
         // 上面是默认解决异样的办法
         // e.printStackTrace();
         System.out.println(e.getMessage());
      }
   }

   // 将异样抛出去
   public static void exceptionTest() throws Exception {
      // 伪装出现异常
      throw new Exception("出现异常");
   }
}

3.3 自定义异样

程序不可能把全副异样创立出,这时咱们就要个性化创立异样。这样的话出现异常,
因为是自定义异样,所有异样解决较好。

3.3.1 自定义编译时异样

  1. 继承 Exception
  2. 重写结构器
  3. 在出现异常中央 throw new 异样类(实参)
// 示例
public class ExceptioTest extends Exception {public ExceptioTest() { }
   public ExceptioTest(String message) {super(message);
   }
}

public class TrcatchTest3 {public static void main(String[] args) {
      try {exceptionTest();
      } catch (Exception e) {
         // 上面是默认解决异样的办法
         // e.printStackTrace();
         System.out.println(e.getMessage());
      }
   }
   public static void exceptionTest() throws Exception {
      // 伪装出现异常
      throw new ExceptioTest("出现异常");
   }
}

3.3.2 自定义运行时异样

  1. 继承 RuntimeException
  2. 重写结构器
  3. 在出现异常中央 throw new 异样类(实参)
public class RuntimeExceptionTest extends RuntimeException {public RuntimeExceptionTest() { }

   public RuntimeExceptionTest(String message) {super(message);
   }
}

public class TrcatchTest3 {public static void main(String[] args) {
      try {exceptionTest();
      } catch (Exception e) {
         // 上面是默认解决异样的办法
         // e.printStackTrace();
         System.out.println(e.getMessage());
      }
   }
   public static void exceptionTest() throws Exception {
      // 伪装出现异常
      throw new ExceptioTest("出现异常");
   }
}

本章完结,用于集体学习和小白入门,大佬勿喷!心愿大家多多点赞珍藏撑持撑持!

源码【GitHub】【码云】

退出移动版