If you are open to using a third party library, the following solution works using Eclipse Collections:
MutableList<String> decryptedPasswordInPairs = Lists.mutable.with("A2")
.collectWith((oddPair, A5) ->
CharAdapter.adapt(oddPair)
.injectIntoWithIndex(
ByteLists.mutable.empty(),
(bytes, character, index) ->
bytes.with((byte) (character ^ A5.charAt(index % A5.length()))))
.makeString(""), "A5");
decryptedPasswordInPairs.each(System.out::println);
I used the following imports:
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.primitive.ByteLists;
import org.eclipse.collections.impl.string.immutable.CharAdapter;
By using the primitive ByteList
available in Eclipse Collections, I was able to avoid boxing. The method makeString
which is available on ByteList
allows you to control the separator. Passing in an empty String
gets rid of the comma that you get using toString
on a List
. The class CharAdapter
provides a set of char
based protocols around String
including the method I used here named injectIntoWithIndex
.
The code can also be broken into smaller steps to make it slightly less dense and potentially easier to read.
MutableList<String> decryptedPasswordInPairs = Lists.mutable.with("A2")
.collect(CharAdapter::adapt)
.collectWith((oddPair, A5) ->
oddPair.injectIntoWithIndex(
ByteLists.mutable.empty(),
(bytes, character, index) ->
bytes.with((byte) (character ^ A5.charAt(index % A5.length())))), "A5")
.collectWith(ByteList::makeString, "");
decryptedPasswordInPairs.each(System.out::println);
Note: I am a committer for Eclipse Collections.