Java17中使用Stream(8->11遇到的问题)

问题来源于一段写自Java 8的代码

JSONArray paramJsonArray = cmdJson.getJSONArray("paramArray");
paramArray = paramJsonArray.stream()
    .map(Object::toString).collect(Collectors.toList());

这段代码升级到Java 17之后出现了编译错误


截屏2022-08-17 10.56.19.png

一、对于Collect操作的变化

  1. Collectors.toUnmodifiableList()支持了不可变的搜集器
  2. Stream.toList()支持了转List的操作符

二、实际的使用

用法 可变性 容null性
Collectors.toList() 可变 可null
Collectors.toUnmodifiableList() 不可变 不可null
Stream.toList() 不可变 可null

demo:

@ExtendWith(MockitoExtension.class)
class DemoTest {
    /**
     * 正常情况
     */
    @Test
    void test1() {
        var source = new ArrayList();
        source.add("1");
        source.add("2");
        source.add(null);
        // 正常数据 可修改,可处理空数据
        List list1 = source.stream().collect(Collectors.toList());
        list1.add("4");
        // UnmodifiableList 引用了java.util.ImmutableCollections,不支持null
        assertThatThrownBy(() -> {
            source.stream().collect(Collectors.toUnmodifiableList());
        }).isInstanceOf(NullPointerException.class);
        List list2 = source.stream().filter(Objects::nonNull).collect(Collectors.toUnmodifiableList());
        assertThatThrownBy(() -> {
            list2.add("4");
        }).isInstanceOf(UnsupportedOperationException.class);
        // toList操作符 不支持修改,不能存null
        List list3 = source.stream().toList();
        assertThatThrownBy(() -> {
            list3.add("4");
        }).isInstanceOf(UnsupportedOperationException.class);
    }
}

三、范型遇到的问题

在Java8中对于Raw type的容器对象,为了方便序列化的读写操作会将其转换成String或者二进制数据,所以经常会有下面的操作

List rawList = new ArrayList();
rawList.add("1");
rawList.add("2");
List ret = rawList.stream().map(Object::toString).collect(Collectors.toList());

这样拿到ret之后可以再进行整体的读写操作,其实rawList.stream()这块的linq操作执行的结果是产生了一个Stream的数据流,交给map变换成Stream
但是同一段代码在Java17中会直接得到一个类型转换错误

List ret = Stream.of("null",123)
       .map(Object::toString).collect(Collectors.toList());

其实整件事情的重点在于对范型的理解和java 11引入的var关键字

  1. java确实存在范型擦出,在编译之后处理的都是Object,但是无论从字节码的角度看,还是从语义的角度看List和List是有区别的
  2. java11由于引入了var,实际上对于List和List的stream操作的语义推断返回值是不同的,前者返回的Stream,后者返回的是Stream

    明确了上述两点,再来看下下面的代码

    List tt = new ArrayList();
    tt.add("111");
    tt.add("222");
    // Java8下编译错误,两者都是编译错误,因为collect(Collectors.toList())返回的是Object
    List e1 = tt.stream().map(param -> param.toString()).collect(Collectors.toList());
    List e2 = tt.stream().map(param -> param.toString()).collect(Collectors.toList());
    // Java8下正确编译
    Stream s8 = tt.stream();
    List ret8 = s8.map(Object::toString).collect(Collectors.toList());
    // Java11下正确编译,但是提示raw type
    Stream s11 = paramJsonArray.stream();
    List ret11 = s11.map(Object::toString).collect(Collectors.toList());
    
     
    
                                
                            
                        
                        
                        

    你可能感兴趣的:(Java17中使用Stream(8->11遇到的问题))