HƯỚNG DẪN Stream or NOT Stream ?

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
Hi

Shakespeare philosophized "To be or not to be..." as if he knew that his thought would be valid forever. And that is true. Modern Technology covers every aspect in our life and makes our life easier. Easier ? Well, it's the Shakespeare question "To be or NOT to be". Those who make the technology become wiser and wiser (and richer and richer). Those who use the technology their life becomes EASIER and EASIER (and dumber and dumber).

Why? Is it a contradiction? No. Technology is a knife with two sharpest edges. You can cut yourself with it. The more you depend on technology the dumber you will be. I have asked the forum Regular Expression or Not? and showed you how modern technology could cause more problems than making a life easier. If a computer becomes sluggish it is NOT that the computer is always obsoleted, BUT it is usually that the users (or programmers) don't know how to work with it. A car is used to transport. Less car = less jam. More car = more jam. Just look at the streets in Saigon or in Hanoi. Everyday there is somewhere in Hanoi or in Saigon the choked jammed streets for hours. The jam is not caused by the car (modern technology), but the people won't use the car correctly. Same to this phenomenon newbie-programmers jump headless into the newfangled Programming Techniques and cause the jams in their computer and on the (inter)net.

Working with Stream is similar with driving a car. Headless use causes worse effect than help. Regular Expression fools the programmers with less coding lines, but in reality it generates more than the wanna-be-modern programmers could believe. The same happens with Stream. Newbie-Programmers choke the computer with Stream. According to Jamie Zawinski's quote:
Some people, when confronted with a problem, think "I know, I'll use STREAM." Now they have TWO problems.
The TWO problems are:
  1. hard to detect hidden bugs
  2. slow due to overhead of Context Switches
Instead of using Stream wisely some programmers use Stream blindly as if Stream is the matter of success-or-failure in their professional life. And when problems arise they blame either the hardware is obsolete or JAVA is unmodern and then they try to switch the language: C# then PYTHON then KOTLIN and then back to JAVA...Funny, isn't it?

The following examples shows you the same solution. One with Stream coding and the other with "normal" coding.

Given:
Java:
String S = "aaHello bbobby AaHic aadDev aaException aff ggaa aaHeroh aaIsMe aAjNO";
Problem: looking for all words which begin with "aa" , turn them to uppercase and finally put them in column on a JTextArea

Solution with Stream
Java:
      JTextArea ta = new JTextArea();
      java.util.List<String> myList = Arrays.asList(S.split(" "));
      long t0 = System.nanoTime();
      Arrays.asList(myList
          .stream()
          .filter(s -> s.startsWith("aa"))
          .collect(Collectors.joining("\n")))
          .stream()
          .map(String::toUpperCase)
          .forEach(ta::append);
Solution with conventional for-loop
Java:
    JTextArea ta = new JTextArea();
    String[] array = S.split(" ");
    for (int i = 0; i < array.length; ++i) {
      if (array[i].startsWith("aa")) ta.append(array[i].toUpperCase()+"\n");
    }
The conventional codes are clearer, but less sophisticated than the Stream solution. But at the expense of a big JAM. The full codes:
Java:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.stream.Collectors;
//
public class TestStream extends JFrame implements ActionListener {
  public TestStream(String S) {
    this.S = S;
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    but1 = new JButton("Stream");
    but1.addActionListener(this);
    but1.setBackground(Color.green);
    JButton but2 = new JButton("SelfMade");
    but2.addActionListener(this);
    but2.setBackground(Color.red);
    JPanel jp = new JPanel();
    jp.add(but1);
    jp.add(but2);
    ta = new JTextArea();
    ta.setBackground(Color.black);
    ta.setForeground(Color.white);
    JScrollPane js = new JScrollPane(ta);
    js.setAutoscrolls(true);
    add("North", jp);
    add("Center", js);
    setSize(550, 300);
    setVisible(true);
  }
  public void actionPerformed(ActionEvent e) {
    ta.append("\n");
    if (e.getSource() == but1) {
      java.util.List<String> myList = Arrays.asList(S.split(" "));
      long t0 = System.nanoTime();
      Arrays.asList(myList
          .stream()
          .filter(s -> s.startsWith("aa"))
          .collect(Collectors.joining("\n")))
          .stream()
          .map(String::toUpperCase)
          .forEach(ta::append);
      t0 = System.nanoTime() - t0;
      ta.append("\nStream Processing Time:"+((double)t0/1000)+" microSec.");
      return;
    }
    String[] array = S.split(" ");
    long t0 = System.nanoTime();
    for (int i = 0; i < array.length; ++i) {
      if (array[i].startsWith("aa")) ta.append(array[i].toUpperCase()+"\n");
    }
    t0 = System.nanoTime() - t0;
    ta.append("\nSelfMade Processing Time:"+((double)t0/1000)+" microSec.");
  }
  private String S;
  private JTextArea ta;
  private String fName;
  private JButton but1;
  public static void main(String... a) throws Exception {
    new TestStream(a.length == 0?
             "aaHello bbobby AaHic aadDev aaException aff ggaa aaHeroh aaIsMe aAjNO":a[0]);
  }
}
stream.png
25.7 milliSeconds versus 1.4 milliSeconds. A very big JAM of ~24 times.
And the bug?
The Newline in the last line AAISME is missed. And it's hard, very hard to remote this bug.

So. The question is
WHY JAVA GIVES A LOT OF EFFORD TO INCLUDE SUCH THE NEWFANGLED FEATURES?
The answer is: When such a Stream loop is started it always takes a lot of time. BUT: when the codes are already in Cache (and won't be moved out by Garbage-Collector) the Stream works
perfectly fast. Especially if the task can be executed parallelly. You could click repeatedly both buttons you will see the wonder of Stream. In essence: Stream is ONLY useful for the case that the solution is REUSED often, very often...Not for once and forget.
 
Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
I click SelfMade first and .... process slower than Stream. You try?
IDE usually caches the standard API codes (stream, string, etc.) to reduce the (Class) loading time.
Secondly, JVM also caches the API codes when they are repeatedly reused
 

ngtheanh.dev

New Member
25/12/20
12
5
3
Hà Nội
Arrays.asList(myList .stream() .filter(s -> s.startsWith("aa")) .collect(Collectors.joining("\n"))) .stream() .map(String::toUpperCase) .forEach(ta::append);
Tôi có thử viết lại như này và thấy kết quả của stream đã tốt hơn

Java:
Stream.of(myList
        .stream()
        .filter(s -> s.startsWith("aa"))
        .collect(Collectors.joining("\n")))
        .map(String::toUpperCase)
        .forEach(ta::append);
 
  • Like
Reactions: Joe

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
Well, there are lots of roads that lead to Roma or Hanoi.
 

ngtheanh.dev

New Member
25/12/20
12
5
3
Hà Nội
IDE usually caches the standard API codes (stream, string, etc.) to reduce the (Class) loading time.
Secondly, JVM also caches the API codes when they are repeatedly reused
Okay tôi sẽ thử chạy chương trình bằng command và so sánh kết quả được không? Hi vọng tôi sẽ tìm được điều gì đó mới mẻ.
Theo tôi nghĩ thì vấn đề ở đây là cách chúng ta đang sử dụng Stream như thế nào cho đúng hơn là so sánh công nghệ. Nếu không hy vọng bạn có thể giải thích tại sao nó chậm hơn (theo tôi thấy thì do sử dụng quá nhiều function của Stream không hợp lý cũng là 1 lý do nhưng có thể khắc phục)
 

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
So. The question is WHY JAVA GIVES A LOT OF EFFORD TO INCLUDE SUCH THE NEWFANGLED FEATURES?
The answer is: When such a Stream loop is started it always takes a lot of time. BUT: when the codes are already in Cache (and won't be moved out by Garbage-Collector) the Stream works
perfectly fast. Especially if the task can be executed parallelly. You could click repeatedly both buttons you will see the wonder of Stream. In essence: Stream is ONLY useful for the case that the solution is REUSED often, very often...Not for once and forget.
Nếu không hy vọng bạn có thể giải thích tại sao nó chậm hơn
You could confer THIS. It's, of course, in English and I hope your English is efficient enough to understand the article.
 
Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
...and what did guru Jamie Zawinski talk about the newfangled programming ? He said:
Why should someone have to retrain themselves to use a new application that does the same basic thing as the old application, just because something as trivial as the operating system changed out from under them?
The old way with a loop works in most cases faster and easier to detect hidden bugs.
 

ngtheanh.dev

New Member
25/12/20
12
5
3
Hà Nội
You could confer THIS. It's, of course, in English and I hope your English is efficient enough to understand the article.
Không quá khó hiểu bài viết này

Quay lại câu chuyện này nhé:
TWO problems are:
  1. hard to detect hidden bugs
  2. slow due to overhead of Context Switches
The old way with a loop works in most cases faster and easier to detect hidden bugs.
1. Như Joe đã nói rất rõ rằng
Stream is ONLY useful for the case that the solution is REUSED often, very often...Not for once and forget
- Cái ONLY ở đây của Joe là cái cần thiết trong hầu hết mọi chương trình chạy Java. Khi mà xu hướng hiện nay là tối ưu cache thì chúng ta phải tìm cách hạn chế sử dụng nó sao? Hãy học cách sử dụng đúng và áp dụng vào bài toán sao cho hợp lý chứ nhỉ

2. Còn việc "detect hidden bugs" trong chương trình thì có rất nhiều cách giúp lập trình viên detect nhanh và hiệu quả hơn việc một thuật toán phức tạp để giải quyết 1 vấn đề nhỏ như trên mà đã được xử lý tốt nhờ "NEWFANGLED FEATURES" (và việc detect tốt đó cũng là nhờ công nghệ phát triển góp phần đó).

Cái gì cũng có 2 mặt. Nhưng đầu tiên code phải chạy đúng đã. Tối ưu là câu chuyện về sau và kinh nghiệm làm việc sẽ làm tốt điều đó. Việc sử dụng các tính năng mới trong Java giúp code dễ đọc hơn, thời gian phát triển được rút ngắn hơn, tập trung vào nghiệp vụ chương trình nhiều hơn (tương tự với việc sử dụng các framework) và đánh đổi lại là "TWO problem" kể trên nhưng tôi tin chỉ cần thường xuyên update kiến thức thì 2 vấn đề đấy không lớn quá đâu.

Nói vậy không phải tôi đánh giá thấp việc tối ưu hiệu năng trong khi code. Đương nhiên là mỗi dòng code mình viết ra nếu không chắc hoặc chưa bao giờ làm tôi luôn google best practice. Quan trọng vẫn là nhìn ra được bài toán cần giải quyết là gì rồi mới sử dụng thuật toán tốt nhất. Các bài toán giải thuật trong trường đa số ít gặp trong dự án thật và nó ở dạng rất khó nhìn thấy.

Và tất nhiên tôi rất cảm ơn về mọi chia sẻ của Joe vì Joe thực sự rất giỏi và hiểu biết cực kì sâu. Tôi đoán Joe phải có tới hàng chục năm kinh nghiệm còn tôi thì mới bắt đầu lập trình được mấy năm thôi :D. Chỉ là một chút chia sẻ về góc nhìn về vấn đề old way và new way. Hi vọng tiếng Việt của Joe đủ tốt để hiểu lời của tôi (bạn cứ viết English vì tôi đọc chúng tốt như đọc document vậy :)))
 
  • Like
Reactions: Joe

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
  1. The "hard to detect hidden bugs" is in the context that it's difficult to catch Exceptions within a long stream without having to go functionally Lambda (which requires final objects and that makes the matter becoming worse.)
  2. Many developers forget to think like an user who has to work with the product. Developers always have plenty time to play with their software, but the users will be boring or nervous if they have to wait for a response of an action. A software product (or app) is useless if it is sluggish. For example the link to the site Vietjet given by a member (HERE) is almost unreachable. Too slow! And that drives the users away.
 
Sửa lần cuối:

ngtheanh.dev

New Member
25/12/20
12
5
3
Hà Nội
1. Tôi chưa hiểu rõ ý phần này lắm
2.
For example the link to the site Vietjet given by a member (HERE) is almost unreachable. Too slow
Website này theo tôi biết được đặt máy chủ tại VN và mục đích phục vụ cho nhu cầu trong nước vì vậy tốc độ truy cập từ nước ngoài chậm hơn rất nhiều so với trong nước. Tôi đã vào thử link này và thấy trải nghiệm hoàn toàn bình thường vì đơn giản là trang web này cũng không có chức năng nhiều nên nếu có chậm thì chắc là do đường truyền
 

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
1. Tôi chưa hiểu rõ ý phần này lắm
2.

Website này theo tôi biết được đặt máy chủ tại VN và mục đích phục vụ cho nhu cầu trong nước vì vậy tốc độ truy cập từ nước ngoài chậm hơn rất nhiều so với trong nước. Tôi đã vào thử link này và thấy trải nghiệm hoàn toàn bình thường vì đơn giản là trang web này cũng không có chức năng nhiều nên nếu có chậm thì chắc là do đường truyền
No. You erred. The way how the Internet routes the requests is usually unpredictable. It's about the load-balancing between the nodes. For example: If the Node Server in Hanoi is overloaded (congested) requests could be routed via Bangkok to Singapore back to the users in Saigon.

Secondly, it also depends on the content how it is implemented. If a page is full of unoptimized images which are usually made by camera and have more than several M pixels then the uploading could take hours. JPEG or PNG could reduce the size perceivably without worsening the image quality (e.g. Windows Paint can do the job very well). Then the redundancy, the bad coding of jsp or servlet or the html (or xhtml) take a lot of processing time for the presentation.
 
  • Like
Reactions: ngtheanh.dev