简体   繁体   English

Java stream parallelStream How to map multple functions to stream map

[英]Java stream parallelStream How to map multple functions to stream map

i have this code that works on Arraylist each element in the array list need to be work by ArithmeticBBB and ArithmeticCCC and create 2 elements which be returned back to the stream im using stream = stream.map(a::work); i have this code that works on Arraylist each element in the array list need to be work by ArithmeticBBB and ArithmeticCCC and create 2 elements which be returned back to the stream im using stream = stream.map(a::work); in the loop.在循环。 or using flatMap或使用 flatMap

class ArithmeticBBB implements ArithmeticManagerStream.ArithmeticAction {
        @Override
        public String arithmetic(String n) {
            String ss  = n+" 2" + " ,Thread ID:" +Thread.currentThread().getId();
            return ss;
        }
    }
    class ArithmeticCCC implements ArithmeticManagerStream.ArithmeticAction {
        @Override
        public String arithmetic(String n) {
            String ss  = n+" 3" + " ,Thread ID:" +Thread.currentThread().getId();
            return ss;
        }
    }
    
    public class ArithmeticManagerStream {
        private List<String> integerList = null;
        private List<String> resultArray = null;
    
    
        public ArithmeticManagerStream(List<String> dataFromUser) {
            this.integerList =  dataFromUser;
        }
    
        public List<String> invokerActions(List<ArithmeticAction> actions) throws
                InterruptedException {
    
            Stream<String> stream = integerList.parallelStream();
            for (final ArithmeticManagerStream.ArithmeticAction a : actions) {
                stream = stream.flatMap(str -> actions.stream().map(b -> b.arithmetic(str)));
             }
            return resultArray = stream.collect(Collectors.toList());
        }
        public interface ArithmeticAction {
            String arithmetic(String n);
        }
    
        public static void main(String[] args) {
            List<ArithmeticAction> actions = new ArrayList();
            actions.add(new ArithmeticBBB());
            actions.add(new ArithmeticCCC());
            List<String> intData = new ArrayList<>();
            intData.add("1");
            intData.add("2");
            intData.add("3");
    
            ArithmeticManagerStream arithmeticManagerStream = new ArithmeticManagerStream(intData);
    
            try {
                List<String> result = arithmeticManagerStream.invokerActions(actions);
                System.out.println("***********************************************");
                for(String i : result) {
                    System.out.println(i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

currently, if you run this program you will see that the results are connected to the string.目前,如果您运行此程序,您将看到结果已连接到字符串。

1 2 ,Thread ID:12 2 ,Thread ID:12
1 2 ,Thread ID:12 3 ,Thread ID:12
1 3 ,Thread ID:12 2 ,Thread ID:12
1 3 ,Thread ID:12 3 ,Thread ID:12
2 2 ,Thread ID:1 2 ,Thread ID:1
2 2 ,Thread ID:1 3 ,Thread ID:1
2 3 ,Thread ID:1 2 ,Thread ID:1
2 3 ,Thread ID:1 3 ,Thread ID:1
3 2 ,Thread ID:13 2 ,Thread ID:13
3 2 ,Thread ID:13 3 ,Thread ID:13
3 3 ,Thread ID:13 2 ,Thread ID:13
3 3 ,Thread ID:13 3 ,Thread ID:13

what i need that each element will be in its own element eg:我需要每个元素都在自己的元素中,例如:

1 2 ,Thread ID:12 
1 2 ,Thread ID:12  
1 3 ,Thread ID:12  
1 3 ,Thread ID:12 
2 2 ,Thread ID:1  
2 2 ,Thread ID:1 
2 3 ,Thread ID:1 
2 3 ,Thread ID:1 
3 2 ,Thread ID:13 
3 2 ,Thread ID:13  
3 3 ,Thread ID:13  
3 3 ,Thread ID:13 

Clearly, the code in the posted question hasn't been stripped down from actual running code, due to the number of typos and other issues.显然,由于拼写错误和其他问题的数量,已发布问题中的代码并未从实际运行的代码中删除。 So it's impossible to tell what the actual problem was.因此,无法判断实际问题是什么。

However, the following code does run:但是,以下代码确实运行:

public class ParallelStreams {

    public static void main(String[] args) {

        List<String> strList = List.of("a1", "a2", "a3", "a4", "a5");
        List<IWork> w = List.of(new Work1(), new Work2());

        Stream<String> stream = strList.parallelStream();
        for (final IWork a : w) {
            stream = stream.map(a::work);
        }
        List<String> finalArray = stream.collect(Collectors.toList());

        for (String s : finalArray) {
            System.out.println(s);
        }
    }
}


interface IWork {
    String work(String s);
}

class Work1 implements IWork {
    @Override
    public String work(String s) {
        return s + " * " + Thread.currentThread().getId();
    }
}

class Work2 implements IWork {
    @Override
    public String work(String s) {
        return s + " ! " + Thread.currentThread().getId();
    }
}

and produces the following output:并产生以下 output:

a1 * 13 ! 13
a2 * 13 ! 13
a3 * 1 ! 1
a4 * 1 ! 1
a5 * 1 ! 1

In order to make it a little clearer as to which IWork implementation was running, I added either a " * ", or ". " in place of the space in the original implementations.为了更清楚地了解运行的是哪个 IWork 实现,我添加了“*”或“.”来代替原始实现中的空格。

First off, thanks for changing this to runnable code so we can see what's going on.首先,感谢您将其更改为可运行代码,以便我们了解发生了什么。

You've made it a little harder to understand because the data is just single digits, while your actions are just single digits and the thread id's can be single digits.由于数据只是个位数,而您的操作只是个位数,线程 ID 可以是个位数,因此您的理解变得更加困难。 So I've changed the data to "A", "B", and "C" to make it easier.所以我将数据更改为“A”、“B”和“C”以使其更容易。

In your for loop, you're looping around actions , but don't actually use the action for anything in the loop.在您的for循环中,您正在循环actions ,但实际上并没有将action用于循环中的任何内容。 So it's essentially just a loop that runs as many times as you have actions, but doesn't differ in each iteration.所以它本质上只是一个循环,运行次数与您的操作一样多,但在每次迭代中都没有不同。 You've made this more difficult to catch because you've called the loop variable a .由于您调用了循环变量a ,因此您使这更难捕捉。 Try naming it something more meaningful.尝试将其命名为更有意义的名称。

What gets really confusing is that you're looping through actions and then streaming actions inside the loop.真正令人困惑的是,您正在循环actions ,然后在循环内流式传输动作。 So this squares the number of actions applied.因此,这将应用的操作数平方。 I can't believe that's what you're looking for, but you don't seem to be upset about that aspect of your output, just the fact that it's merged for each input.我不敢相信这就是您要寻找的东西,但您似乎并不对 output 的这方面感到不安,只是因为每个输入都合并了它。

Also, it's not clear how much you care about the threads themselves.此外,尚不清楚您对线程本身的关心程度。 You have them in the output, but why?您在 output 中有它们,但为什么呢? Why use ParallelStream() ?为什么使用ParallelStream()

You are also making it far more complicated by treating the Stream as a variable and moving it through steps.通过将 Stream 视为变量并逐步移动它,您还可以使它变得更加复杂。 In the first answer I posted, I found that combining it all together resulted in the entire stream running through a single Thread, so I didn't do that in that answer since I wasn't sure how important the threads were to you (and they shouldn't be).在我发布的第一个答案中,我发现将它们组合在一起会导致整个 stream 通过单个线程运行,所以我没有在那个答案中这样做,因为我不确定线程对你有多重要(并且他们不应该)。

In the end, it works perfectly if you dump the for loop, and then combine it all into a single Stream statement:最后,如果您转储for循环,然后将其全部组合成一个 Stream 语句,它会完美运行:

class ArithmeticBBB implements ArithmeticManagerStream.ArithmeticAction {
    @Override
    public String arithmetic(String n) {
        String ss = n + " 2" + " ,Thread ID:" + Thread.currentThread().getId();
        return ss;
    }
}

class ArithmeticCCC implements ArithmeticManagerStream.ArithmeticAction {
    @Override
    public String arithmetic(String n) {
        String ss = n + " 3" + " ,Thread ID:" + Thread.currentThread().getId();
        return ss;
    }
}

public class ArithmeticManagerStream {
    private List<String> integerList = null;
    private List<String> resultArray = null;


    public ArithmeticManagerStream(List<String> dataFromUser) {
        this.integerList = dataFromUser;
    }

    public List<String> invokerActions(List<ArithmeticAction> actions) throws InterruptedException {
        return integerList.parallelStream()
                          .flatMap(str -> actions.stream().map(action -> action.arithmetic(str)))
                          .collect(Collectors.toList());
    }

    public interface ArithmeticAction {
        String arithmetic(String n);
    }

    public static void main(String[] args) {
        List<ArithmeticAction> actions = new ArrayList();
        actions.add(new ArithmeticBBB());
        actions.add(new ArithmeticCCC());
        List<String> intData = new ArrayList<>();
        intData.add("A");
        intData.add("B");
        intData.add("C");

        ArithmeticManagerStream arithmeticManagerStream = new ArithmeticManagerStream(intData);

        try {
            List<String> result = arithmeticManagerStream.invokerActions(actions);
            System.out.println("***********************************************");
            for (String i : result) {
                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

This results in:这导致:

***********************************************
A 2 ,Thread ID:13
A 3 ,Thread ID:13
B 2 ,Thread ID:1
B 3 ,Thread ID:1
C 2 ,Thread ID:1
C 3 ,Thread ID:1

That seems about right to me.这对我来说似乎是正确的。 Each source item passes through each of the actions, generating it's own output which is flatmapped back into the original stream.每个源项都通过每个动作,生成它自己的 output,它被平面映射回原始 stream。

A final note.最后一点。 I was looking to streamline the code, and noticed that your interface is a Functional construct.我正在寻找简化代码,并注意到您的界面是一个Functional构造。 So you could actually ditch the implementation classes and just declare them with a lambda when you load up the actions array.因此,您实际上可以放弃实现类,并在加载actions数组时使用 lambda 声明它们。 Then, of course, it became obvious that your interface is basically a Function<String, String> .然后,当然,很明显你的接口基本上是一个Function<String, String> So I ditched the interface altogether and then cleaned up the code, using a Stream for the final output.所以我完全放弃了接口,然后清理了代码,使用 Stream 作为最终的 output。

The result is essentially trivial, I added a bunch more actions just to make a point:结果基本上是微不足道的,我添加了更多操作只是为了说明一点:

public class ArithmeticManagerStream {
    private List<String> integerList = null;

    public ArithmeticManagerStream(List<String> dataFromUser) {
        this.integerList = dataFromUser;
    }

    public List<String> invokerActions(List<Function<String, String>> actions) {
        return integerList.parallelStream().flatMap(str -> actions.stream().map(action -> action.apply(str))).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        List<Function<String, String>> actions = new ArrayList();
        actions.add(n -> n + " 2" + " ,Thread ID:" + Thread.currentThread().getId());
        actions.add(n -> n + " 3" + " ,Thread ID:" + Thread.currentThread().getId());
        actions.add(n -> n + " 4" + " ,Thread ID:" + Thread.currentThread().getId());
        actions.add(n -> n + " 5" + " ,Thread ID:" + Thread.currentThread().getId());
        actions.add(n -> n + " 6" + " ,Thread ID:" + Thread.currentThread().getId());
        List<String> intData = new ArrayList<>();
        intData.add("A");
        intData.add("B");
        intData.add("C");

        ArithmeticManagerStream arithmeticManagerStream = new ArithmeticManagerStream(intData);
        List<String> result = arithmeticManagerStream.invokerActions(actions);
        System.out.println("***********************************************");
        result.forEach(System.out::println);
    }
}

and the output is: output 是:

***********************************************
A 2 ,Thread ID:13
A 3 ,Thread ID:13
A 4 ,Thread ID:13
A 5 ,Thread ID:13
A 6 ,Thread ID:13
B 2 ,Thread ID:1
B 3 ,Thread ID:1
B 4 ,Thread ID:1
B 5 ,Thread ID:1
B 6 ,Thread ID:1
C 2 ,Thread ID:14
C 3 ,Thread ID:14
C 4 ,Thread ID:14
C 5 ,Thread ID:14
C 6 ,Thread ID:14

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM