主頁 >  其他 > JAVASE學習筆記(十三.1)(jdk新特性(AutoCloseable介面 / Stream流))

JAVASE學習筆記(十三.1)(jdk新特性(AutoCloseable介面 / Stream流))

2021-12-21 14:51:33 其他

JAVASE學習筆記(十三.1)

  • Java7新特性 - `AutoCloseable`
    • 1. 概述
    • 2. 應用場景
      • 示例
      • 如何解決
      • 改進
      • 注意
  • Java8新特性 - `Stream流`
    • 1. 概述
    • 2. Stream的API
    • 3. Stream的認識
      • (1)Stream-流的常用創建方法
        • 面試題
        • stream流使用步驟
        • 準備作業
      • (2)中間操作
        • 1. 過濾:filter
        • 2. 映射改造:peek / map
          • peek和map的區別是什么?
        • 3. 排序:sorted
        • 4. ==distanct==
        • 5. 集合分頁:skip / limit
          • 匿名內部類作用
      • (3)終止操作
          • findFirst& findAny
      • 總結
    • 4. 使用場景

Java7新特性 - AutoCloseable

1. 概述

JDK在1.7之后出現了自動關閉類的功能,該功能的出現為各種關閉資源提供了相當大的幫助,這里我們談一談自動關閉類,

JDK1.7之后出現了一個重要的介面,以及改造了一個重要的方法結構:

  • AutoCloseable自動關閉介面
  • try(){}–catch{}–finally{}

相應的 一些資源也實作了該介面,如PreparedStatement、Connection、InputStream、OutputStream等等資源介面,

2. 應用場景

示例

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyLockDemo {
    static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        try {
            lock.lock();
            System.out.println("1-----加鎖成功!!!");
            System.out.println("2-----開始執行業務邏輯");
            Thread.sleep(3000);
            System.out.println("3-----業務執行完畢");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("4----釋放鎖資源");
        }
    }

}

如上,在開發中鎖是釋放必須要做得事情,所以就把放在finally中來執行,但是在開發中往往很多的開發中,都會忘記釋放鎖或者忘記把鎖的釋放放入finally中,就造成死鎖現象,這個很危險的操作和行為,

如何解決

  • 使用AutoCloseable介面覆寫close方法

實作AutoCloseable介面,
覆寫close方法,
把原來要寫finally中釋放資源的動作,放入到close方法中去執行,
而這個執行是jvm自己去執行.

在有try(){}–catch{}–finally{}的時候去實作

  • 介面的實作類要重寫close()方法,
  • 將要關閉的資源定義在try()中,這樣當程式執行完畢之后,資源將會自動關閉,
  • 自定義類如果要進行自動關閉,只需要實作AutoCloseable介面重寫close()方法即可,

同時也只有實作了AutoCloseable介面才能將自定義類放入到try()塊中,否則編譯不能通過

改進

  1. 定義類MyLock類
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyLock implements AutoCloseable{

    Lock lock = new ReentrantLock();

    // 加鎖
    public void lock() {
        lock.lock();
    }

    // 釋放鎖
    public void unlock() {
        lock.unlock();
    }


    @Override
    public void close() throws Exception {
        unlock();
        System.out.println("4----釋放鎖資源");
    }
}

改進

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyLockDemo {
    public static void main(String[] args) {
        try (MyLock lock = new MyLock();){
            lock.lock();
            System.out.println("1-----加鎖成功!!!");
            System.out.println("2-----開始執行業務邏輯");
            Thread.sleep(3000);
            System.out.println("3-----業務執行完畢");
        } catch (Exception e) {
            e.printStackTrace();
        }//        finally {
//            // 不需要定義了.因為會自動去釋放資源
//            lock.unlock();
//        }
    }
}

1-----加鎖成功!!!
2-----開始執行業務邏輯
3-----業務執行完畢
4----釋放鎖資源  -- 這里的執行就是AutoCloseable中的close方法自動執行的

注意

若是有多個類需要上鎖釋放鎖
在try{}中用“;”隔開
釋放鎖有順序,先上鎖的最后放

Java8新特性 - Stream流

1. 概述

概念:Stream 是Java8 提出的一個新概念,不是輸入輸出的 Stream
流,而是一種函式式編程方式在集合類上進行復雜操作的工具,簡而言之,是以內部迭代的方式處理集合資料的操作,內部迭代可以將更多的控制權交給集合類,Stream和 Iterator 的功能類似,只是 Iterator 是以外部迭代的形式處理集合資料的操作,

總結:Stream 是Java8 的新特性,它是基于Lambda運算式在集合陣列等進行一系列的優化和操作的工具集,解決集合中一些像過濾,排序,分組,聚合,改造等一系列的問題,

在Java8以前,對集合的操作需要寫出處理的程序,如在集合中篩選出滿足條件的資料,需要一 一遍歷集合中的每個元素,再把每個元素逐一判斷是否滿足條件,最后將滿足條件的元素保存回傳,而Stream 對集合篩選的操作提供了一種更為便捷的操作,只需將實作函式介面的篩選條件作為引數傳遞進來,Stream會自行操作并將合適的元素同樣以Stream 的方式回傳,最后進行接收即可,

  • 集合和陣列在遍歷元素的時候十分冗余,受到函式式編程以及流水線思想的啟發,我們可以將常見的操作封裝成比較簡單的方法,比如遍歷的時候直接呼叫一個方法即可,而不用寫冗余的回圈程式,這就是Stream流物件的由來,
  • Stream是一個介面,有兩種方式來進行創建流物件,
    一是呼叫 Stream.介面中的of方法,
    二是呼叫集合或者陣列中的strain方法來獲取 Stream.流物件
  • Stream物件中常用的方法有:遍歷元素,篩選元素,跳過元素,截取元素,計數,把流物件拼接,對流物件中的資料元素進行轉換,

2. Stream的API

流是javaAPI中的新的成員,它可以讓你用宣告式的方式處理集合,簡單點說,可以看成遍歷資料的一個高級點的迭代器,也可以看做一個工廠,資料處理的工廠,當然,流還天然的支持并行操作;也就不用去寫復雜的多執行緒的代碼,下面是Stream的接口定義

在jdk1.8的java.util.stream.Stream介面,里面定義流的API的方法,jdk集合Collection.java頂級集合,利用默認方法進行了實作,具體的實作是通過:StreamSupport.java實作的,

Stream是處理集合的一套高級的API的解決方案

public interface Stream<T> extends BaseStream<T, Stream<T>> {
 
	Stream<T> filter(Predicate<? super T> predicate);
 
	<R> Stream<R> map(Function<? super T, ? extends R> mapper);
 
	IntStream mapToInt(ToIntFunction<? super T> mapper);
 
	LongStream mapToLong(ToLongFunction<? super T> mapper);
 
	DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
 
	<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
 
	IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
 
	LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
 
	DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
 
	Stream<T> distinct();
 
	Stream<T> sorted();
 
	Stream<T> sorted(Comparator<? super T> comparator);
 
	Stream<T> peek(Consumer<? super T> action);
 
	Stream<T> limit(long maxSize);
 
	Stream<T> skip(long n);
 
	void forEach(Consumer<? super T> action);
 
	void forEachOrdered(Consumer<? super T> action);
 
	Object[] toArray();
 
	<A> A[] toArray(IntFunction<A[]> generator);
 
	T reduce(T identity, BinaryOperator<T> accumulator);
 
	Optional<T> reduce(BinaryOperator<T> accumulator);
 
	<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
 
	<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
 
	<R, A> R collect(Collector<? super T, A, R> collector);
 
	Optional<T> min(Comparator<? super T> comparator);
 
	Optional<T> max(Comparator<? super T> comparator);
 
	long count();
 
	boolean anyMatch(Predicate<? super T> predicate);
 
	boolean allMatch(Predicate<? super T> predicate);
 
	boolean noneMatch(Predicate<? super T> predicate);
 
	Optional<T> findFirst();
 
	Optional<T> findAny();
 
	public static <T> Builder<T> builder() {
		return new Streams.streamBuilderImpl<>();
	}
 
	public static <T> Stream<T> empty() {
		return StreamSupport.stream(Spliterators.<T> emptySpliterator(), false);
	}
 
	public static <T> Stream<T> of(T t) {
		return StreamSupport.stream(new Streams.streamBuilderImpl<>(t), false);
	}
 
	@SafeVarargs
	@SuppressWarnings("varargs") // Creating a Stream from an array is safe
	public static <T> Stream<T> of(T... values) {
		return Arrays.stream(values);
	}
 
	public static <T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
		Objects.requireNonNull(f);
		final Iterator<T> iterator = new Iterator<T>() {
			@SuppressWarnings("unchecked")
			T t = (T) Streams.NONE;
 
			@Override
			public boolean hasNext() {
				return true;
			}
 
			@Override
			public T next() {
				return t = (t == Streams.NONE) ? seed : f.apply(t);
			}
		};
		return StreamSupport.stream(
				Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
	}
 
	public static <T> Stream<T> generate(Supplier<T> s) {
		Objects.requireNonNull(s);
		return StreamSupport.stream(new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s),
				false);
	}
 
	public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
		Objects.requireNonNull(a);
		Objects.requireNonNull(b);
 
		@SuppressWarnings("unchecked")
		Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>((Spliterator<T>) a.spliterator(),
				(Spliterator<T>) b.spliterator());
		Stream<T> Stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
		return Stream.onClose(Streams.composedClose(a, b));
	}
 
	public interface Builder<T> extends Consumer<T> {
		@Override
		void accept(T t);
 
		default Builder<T> add(T t) {
			accept(t);
			return this;
		}
 
		Stream<T> build();
 
	}
}

3. Stream的認識

通過上述介面定義,可以看到,抽象方法,有30多個方法,里面還有一些其他的介面;
上述方法可分為三類:
在這里插入圖片描述

(1)Stream-流的常用創建方法

面試題

stream()parallelStream()兩種流化方法的區別

stream流使用步驟

  1. 流化
  2. 中間操作
  3. 終端操作

準備作業

   //1.創建集合
        List<User> users = new ArrayList<>();
        users.add(new User("月色",18,0));
        users.add(new User("夜雨",16,1));
        users.add(new User("搖光",18,0));
        users.add(new User("流蘇",19,1));
   //2.流化
	    Stream<User> stream = users.stream();
	    Stream<User> userStream = users.parallelStream();
	    List<User> collect = Stream.of(new User("月色", 18, 0), new User("夜雨", 16, 1)).collect(Collectors.toList());

1.1 集合轉流:使用Collection下的 stream() 和 parallelStream() 方法

List<String> list = new ArrayList<>();
Stream<String> Stream = list.stream(); //獲取一個順序流
Stream<String> parallelStream = list.parallelStream(); //獲取一個并行流

1.2 陣列轉流:使用Arrays 中的 stream() 方法

Integer[] nums = new Integer[10];
Stream<Integer> Stream = Arrays.stream(nums);

1.3 使用Stream中的靜態方法:of()、iterate()、generate()

  List<User> collect = Stream.of(new User("月色", 18, 0), new User("夜雨", 16, 1)).collect(Collectors.toList());

Stream.of:把多個物件進行流化處理

Stream<Integer> Stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
Stream2.forEach(System.out::println); // 0 2 4 6 8 10
 
Stream<Double> Stream3 = Stream.generate(Math::random).limit(2);
Stream3.forEach(System.out::println);

1.4 使用 BufferedReader.lines() 方法,將每行內容轉成流

BufferedReader reader = new BufferedReader(new FileReader("F:\\test_Stream.txt"));
Stream<String> lineStream = reader.lines();
lineStream.forEach(System.out::println);

1.5 使用 Pattern.splitAsStream() 方法,將字串分隔成流

Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);

(2)中間操作

intermediate operation 中間操作:中間操作的結果是刻畫、描述了一個Stream,并沒有產生一個新集合,這種操作也叫做惰性求值方法,

對應的方法如下:

這是所有Stream中間操作的串列:
過濾()==>filter()//將滿足條件的過濾出來
地圖==>map()//映射結果,改造資料,有回傳值
轉換()==>flatMap()
不同()==>distinct() 
排序()==>sorted()
窺視()==>peek()//映射結果,改造資料,無回傳值
限制()==>limit()
跳躍()==>skip()
疊加()==>reduce()

1. 過濾:filter

語法:

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

寫法

userList1.stream().filter(new Predicate<User>() {
    @Override
    public boolean test(User user) {
        System.out.println("11111");
        return false;
    }
});
userList1.stream().filter(u-> {
	return u.getAge() > 16;
});

 userList1.filter(u -> u.getAge() > 16)

是過濾,把條件滿足的過濾匹配處理,如下

public class StreamDemo01 {

    public static void main(String[] args) {
        // 1:創建一個集合
        List<User> userList1 = new ArrayList<>();
        userList1 .add(new User("月色",18,0));
        userList1 .add(new User("夜雨",16,1));
        userList1 .add(new User("搖光",18,0));
        userList1 .add(new User("流蘇",19,1));
  
        // 3: 結束操作
        List<User> collect = userList1.stream()
                .filter(u -> u.getAge() > 16) // 把滿足條件的篩選出來
                .collect(Collectors.toList());
        for (User user : collect) {
            System.out.println(user);
        }

    }
}

2. 映射改造:peek / map

屬于:映射 ,它可以改變集合中物件的屬性值

 Stream<T> peek(Consumer<? super T> action);
 <R> Stream<R> map(Function<? super T, ? extends R> mapper);
  • peek操作案例:

把集合中年齡大于16歲的用戶的年齡+1歲,如下

List<User> collect = userList1.stream() // 1: stream流化操作
    .filter(u -> u.getAge() > 16) // // 2:中間操作 filter 把滿足條件的篩選出來
    .peek(u->u.setAge(u.getAge() + 1))// 3:中間操作 peek 把每個用戶的年齡加1歲
    .collect(Collectors.toList());  // 4: 結束操作


for (User user : collect) {
    System.out.println(user);
}
  • map操作案例:
List<User> collect = userList1.stream() // 1: stream流化操作
.filter(u -> u.getAge() > 16) // // 2:中間操作 filter 把滿足條件的篩選出來
.map(u -> {
    u.setAge(u.getAge() + 1);
    return u;
})// 3:中間操作 peek 把每個用戶的年齡加1歲
.collect(Collectors.toList());  // 4: 結束操作
peek和map的區別是什么?
  • peek和map區別:peek無回傳值,map有回傳值(可以改變回傳值)
  • peek你前面集合流化物件回傳的是什么就是什么?
    map可以把stream回傳值進行改變,我可以把集合中的物件改成map在回傳,或者我只需要集合中某個一列的值,
public class StreamDemo02 {

    public static void main(String[] args) {
        // 1:創建一個集合
        List<User> userList1 = new ArrayList<>();
        userList1 .add(new User("月色",18,0));
        userList1 .add(new User("夜雨",16,1));
        userList1 .add(new User("搖光",18,0));
        userList1 .add(new User("流蘇",19,1));


        // user--nickname
        List<String> nicknames = userList1.stream().map(u -> {
            return u.getUsername();
        }).collect(Collectors.toList());

        for (String nickname : nicknames) {
            System.out.println(nickname);
        }

        // user---map
        List<Map<String, Object>> collect = userList1.stream().map(u -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", u.getId());
            map.put("username", u.getUsername());
            map.put("sex", u.getSex()); 
            return map;
        }).collect(Collectors.toList());

        for (Map<String, Object> stringObjectMap : collect) {
            System.out.println(stringObjectMap);
        }


        // user--->uservo
        List<UserVo> collect1 = userList1.stream().map(u -> {
            UserVo userVo = new UserVo();
            userVo.setId(u.getId());
            userVo.setUsername(u.getUsername());
            userVo.setSex(u.getSex() == 1 ? "男" : "女");
            return userVo;
        }).collect(Collectors.toList());

        for (UserVo userVo : collect1) {
            System.out.println(userVo);
        }


    }


}

3. 排序:sorted

public class StreamDemo03 {

    public static void main(String[] args) {
        // 1:創建一個集合
        List<User> userList1 = new ArrayList<>();
         userList1 .add(new User("月色",18,0));
        userList1 .add(new User("夜雨",16,1));
        userList1 .add(new User("搖光",18,0));
        userList1 .add(new User("流蘇",19,1));

//        List<User> sortUserList = userList1.stream().sorted(new Comparator<User>() {
//            @Override
//            public int compare(User o1, User o2) {
//                return o2.getAge() - o1.getAge();
//            }
//        }).collect(Collectors.toList());

//        List<User> sortUserList = userList1.stream().sorted((User o1, User o2) ->{
//                return o2.getAge() - o1.getAge();
//        }).collect(Collectors.toList());

      
        List<User> sortUserList = userList1.stream().sorted((o1, o2) -> o2.getAge() - o1.getAge()).collect(Collectors.toList());
        for (User user : sortUserList) {
            System.out.println(user);
        }

    }

}

4. distanct

去重這里有個坑:去重是通過equal來比較兩者值是否相等來實作去重,但是問題來了:

類似Integer這種型別原始碼已經重寫了equal方法,但是像我們自定義的一些型別,物件,它并沒有重寫equal方法,所以它依舊在比較地址以至于不能完成去重功能,所以我們要使用distabct的時候注意是否需要重寫equal

  • 如果是物件,必須滿足eqauls是true ,并且hashcode要相同
public class User {
    // 身份id
    private Integer id;
    // 姓名
    private String username;
    // 密碼
    private String password;
    // 芳齡
    private Integer age;
    //  性別 0 女 1 男
    private Integer sex;
    // 身家
    private Double money;

    public User(){

    }

    public User(Integer id, String username, String password, Integer age, Integer sex, Double money) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.money = money;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", money=" + money +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(username, user.username) && Objects.equals(password, user.password) && Objects.equals(age, user.age) && Objects.equals(sex, user.sex) && Objects.equals(money, user.money);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, username, password, age, sex, money);
    }
}

public class StreamDemo04 {

    public static void main(String[] args) {
        // 1:創建一個集合
        List<User> userList1 = new ArrayList<>();
        User user1 =  new User(1, "小文", "123456", 16, 1, 20000d);
        User user2 =  new User(1, "小文", "123456", 16, 1, 20000d);
        userList1.add(user1);
        userList1.add(user2);
        userList1.add(new User(2, "老季", "123456", 22, 1, 100000d));
        userList1.add(new User(3, "怪咖", "123456", 13, 1, 89557d));
        userList1.add(new User(4, "小六", "123456", 26, 1, 78000d));
        userList1.add(new User(5, "小劉", "123456", 46, 1, 58000d));


        System.out.println(user1.equals(user2));

        List<User> userList = userList1.stream().distinct().collect(Collectors.toList());
        for (User user : userList) {
            System.out.println(user);
        }

//        List<Integer> userList1 = new ArrayList<>();
//        userList1.add(1);
//        userList1.add(2);
//        userList1.add(3);
//        userList1.add(1);
//
//        List<Integer> collect = userList1.stream().distinct().collect(Collectors.toList());
//        System.out.println(collect);
    }


}

轉換()==>flatMap()
疊加()==>reduce()

5. 集合分頁:skip / limit

public class StreamDemo03 {
    public static void main(String[] args) {
        // 1:創建一個集合
        List<User> userList1 = new ArrayList<>();
        userList1 .add(new User("月色",18,0));
        userList1 .add(new User("夜雨",16,1));
        userList1 .add(new User("搖光",18,0));
        userList1 .add(new User("流蘇",19,1));
        
        int pageSize =2;// 每頁顯示多少條
        int pageno = 1; // 當前頁

        List<User> userpage = pageUser(pageNo,pageSize);


    }
    
    public static List<User> pageUser(int pageNo,int pageSize){
          int skip = (pageNo - 1) * pageSize;
          return  userList1.stream().sorted((o1, o2) -> o2.getAge() - o1.getAge())
                .skip(skip) // (pageno-1) * pageSize
                .limit(pageSize) // pageSize
                .collect(Collectors.toList());
		  //類似分頁
          for(User user : sortUserList){
				system.out.println(user);
		 }
    
    }


}

匿名內部類作用

中間操作經常用Lambda運算式簡化代碼,使用lambda運算式會派生一個介面類,好處是:
把匿名內部類(介面,抽象類)當做方法的引數傳遞以后,它可以達到一個效果就是可以把方法中的一部分邏輯抽離到匿名內部類的方法中去處理

userList1.stream().filter(new Predicate<User>() {
    @Override
    public boolean test(User user) {
        System.out.println("11111");
        return false;
    }
});
userList1.stream().filter(u-> {
	return u.getAge() > 16;
});

 userList1.filter(u -> u.getAge() > 16)

(3)終止操作

terminal operation 終止操作:最侄訓從Stream中得到值,說白了:就是可以直接得到結果

回圈()==>foreach()
count():回傳流中元總個數素
收集()==>collect()---放
andMatch():接受一個`predicate`函式,只要流中有一個元素符合該斷言回傳true,否則回傳false
noneMatch():接受一個`predicate`函式,當流中每個元素都不符合該斷言回傳true,否則回傳false
allMatch():接受一個`predicate`函式,當流中每個元素都符合該斷言回傳true,否則回傳false
min():回傳流中元素最小值
max():回傳流中元素最大值
findFirst& findAny
  • 兩者在stream(串行)的情況下,兩者其實都回傳的第一個元素
  • 如果是parallelStream(并行)情況下findAny就造成隨機回傳

findAny()回傳的元素是不確定的,對于同一個串列多次呼叫findAny()有可能會回傳不同的值,使用findAny()是為了更高效的性能,
如果是資料較少,串行地情況下,一般會回傳第一個結果,
如果是并行的情況,那就不能確保是第一個,

總結

steram流一旦呼叫終止方法就代表流已經操作完畢,不能進行其他操作了
若要重新進行操作
將結果再次轉換為流即可

在這里插入圖片描述

  • 如何區分這2種操作

可以根據操作的回傳值型別判斷:
回傳值是Stream,則該操作是中間操作
回傳值是其他值或者為空,則該操作是終止操作,

如下圖的前2個操作是中間操作,只有最后一個操作是終止操作,

img

可以形象地理解Stream的操作是對一組粗糙的工藝品原型(即對應的 Stream
資料源)進行加工成顏色統一的工藝品(即最終得到的結果),第一步篩選出合適的原型(即對應Stream的 filter
的方法),第二步將這些篩選出來的原型工藝品上色(對應Stream的map方法),第三步取下這些上好色的工藝品(即對應Stream的
collect(toLis t())方法),在取下工藝品之前進行的操作都是中間操作,可以有多個或者0個中間操作,但每個Stream資料源只能有一次終止操作,否則程式會報錯

4. 使用場景

場景:查詢用戶資訊的時候為了安全起見,需要把集合中每個用戶物件的敏感資訊賦值null,在進行回傳,

  • 版本8之前:新建list
List<User> userList = new ArrayList();
List<User> newList = new ArrayList();
for(User user : userList){
	user.setPassword = null;
	newList.add(user);
}
  • 版本8之后:stream流化

  • peek解決:

 List<User> userList = userList1.stream().peek(u -> u.setPassword("")).collect(Collectors.toList());
 userList.forEach(System.out::println);
  • map解決
List<User> userList2 = userList1.stream().map(u -> {
    u.setPassword("");
    return u;
}).collect(Collectors.toList());
userList2.forEach(System.out::println);

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/388251.html

標籤:其他

上一篇:JavaWeb(一)——JavaWeb介紹、Tomcat服務器、HTTP協議

下一篇:Log4j漏洞修復方案

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more