1

after reading about streams I am trying to use them now and already with simple examples the first questions arise. I would like to implement a very simple encryption algorithm, which uses substitution. There is some text to be encrypted:

static List<Integer> text = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20);

There is some password:

private List<Integer> password = Arrays.asList(1, 5, 7, 3);

The idea is now to add the password values to the text values. The result should be

1+1, 2+5, 3+7, 4+3, 5+1, 6+5, ...

So I have to create a stream from password, which starts from the beginning when reaching the end of the above list. This part I already managed to do.

Now I somehow have to merge 2 streams into 1 stream. Any ideas, how to accomplish that?

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
micgn
  • 245
  • 1
  • 4
  • 14

2 Answers2

5

I would probably stream indexes here:

IntStream.range(0, text.size())
         .map(i -> text.get(i) + password.get(i % password.size())
         .toArray();
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    I think you need to call `boxed()` before you can collect the IntStream. Or am I wrong? – Roland Dec 04 '14 at 10:45
  • 3
    @Roland: yes, but you can also use `mapToObj` instead of `map`, then you don’t need to call `boxed()` afterwards. Or you use `toArray()` instead of `collect(toList())` as the OP didn’t specify what to do with the `Stream` afterwards. – Holger Dec 04 '14 at 11:40
  • This is using a simple stream instead of a for loop like below. Although this is a functional expression, my intention really was to stream the content of a large file and also to stream the password. Although the solution is very valid I wanted to learn if streams can be merged... – micgn Dec 04 '14 at 12:20
  • 1
    @micgn I'm not sure how you envisage to do that - you would need to "iterate" over the streams in parallel and recreate the password stream every time you reach its end. I don't think there is an easy way to do that. – assylias Dec 04 '14 at 12:37
  • @assylias: You *can* create an infinite `Stream` for a repeating sequence, e.g. `Stream.generate(()->password).flatMap(Collection::stream)`. But after then, it will turn out to be tricky. There are solutions presented [here](http://stackoverflow.com/questions/24059837/iterate-two-java-8-streams-together) and [Here](http://stackoverflow.com/questions/17640754/zipping-streams-using-jdk8-with-lambda-java-util-stream-streams-zip) (surprisingly, no-one vote for duplicate), but combining an infinite stream with a finite one may cause problems. – Holger Dec 05 '14 at 17:13
  • 1
    Well, if you know the size of the `text`, you can create an equal-sized password stream like `IntStream.rangeClosed(0, text.size()).map(i -> password.get(i%password.size()))` or, if it isn’t an ordinary `Collection`: `LongStream.rangeClosed(0, textSize).mapToInt(l -> password.get((int)(l%password.size())))` but still, combining these two streams may work somehow, but isn’t better than the one-stream solution presented here. Only if either, text size or password size exceeds `Long.MAX_VALUE` we have to rethink… – Holger Dec 05 '14 at 17:16
0

These are lists your result will also be a list.

You you create a new List crypt = new ArrayList(); then you loop through the text list and for each item in the text list you add the value in the password list index that is the index in the text list % password.size();

List<Integer> crypt= new ArrayList<Integer>();
for(int index= 0;index=<text.size();index++){
    crypt.add(text.get(index)+password.get(index % password.size());
}
Matthew V Carey
  • 196
  • 1
  • 10
  • yes, right! But I want to learn streams. It is of course bit of a question if it would get more concise/clean/beautiful with streams... – micgn Dec 04 '14 at 12:15
  • Yes, I answered the question missing the point but, there is a view that rather than being concise and clean we don't run the risk of being a just bit mysterious, about what we are up to. – Matthew V Carey Dec 04 '14 at 12:26