4

I try to filter a byte[], I want to remove line breaks from the stream

byte[] data = "y\neahbabydoit\nsothisistheway\ntodoit".getBytes();
Object[] tmp = IntStream.range(0, data.length).mapToObj(idx -> Integer.valueOf(data[idx]).byteValue()).filter(i -> i != 10).toArray();
System.out.println("src:"+Arrays.toString(data));
System.out.println("dst:"+Arrays.toString(tmp));

//works not!!
byte[] dest = (Byte[]) tmp; //help me here

The result (as expected) works (so far) but I'm not able to convert the result (Object[]) in an easy way back (to byte[])...

src:[121, 10, 101, 97, 104, 98, ...
dst:[121, 101, 97, 104, 98, 97, ...

I know there are ways to solve this problem (see How to convert int[] to byte[]) but I want to do it in an easy (stream-like) way...

any news from java 8 or later?

Mureinik
  • 277,661
  • 50
  • 283
  • 320
Martin Frank
  • 3,351
  • 1
  • 27
  • 45

3 Answers3

2

To save yourself the hassle of handling multi-byte characters, it may be a lot easier to just handle the stream of characters:

String result =
    data.chars()
        .filter(c -> c != '\n')
        .mapToObj(c -> String.valueOf((char) c))
        .collect(Collectors.joining());
Mureinik
  • 277,661
  • 50
  • 283
  • 320
  • 2
    Or just `data.replace("\n", "");` – Jacob G. Jul 06 '18 at 19:04
  • 2
    @JacobG. better for the general task of “removing linebreaks” would be `data.replaceAll("\\R", "");` – Holger Jul 07 '18 at 13:33
  • @Holger Right but `data.replace("\n", "")` will not work either as it is not a String but a `byte[]`. Or else : `new String(data, StandardCharsets.UTF_8).replace(...)` – davidxxx Jul 07 '18 at 13:40
  • 2
    @davidxxx if `data` was a `byte[]`, there was no `chars()` method either. Both, this answer and JacobG’s comment use the fact that the OP initially had a `String` before querying the byte array. The answer also recommends processing characters instead of bytes. – Holger Jul 07 '18 at 13:43
  • @ Holger Ah okiiiiiii. I didn't get it. It is clear now. Thanks. – davidxxx Jul 07 '18 at 13:44
2

As @Mureinik suggested, it is better to deal with characters rather than bytes, to answer your question, you can certainly use something like

Byte[] tmp = IntStream.range(0, data.length)
        .mapToObj(idx -> Integer.valueOf(data[idx]).byteValue())
        .filter(i -> i != 10)
        .toArray(Byte[]::new);
Patrick Parker
  • 4,633
  • 3
  • 18
  • 47
RP-
  • 5,807
  • 2
  • 26
  • 43
  • 4
    `.mapToObj(idx -> Integer.valueOf(data[idx]).byteValue())` will read a `byte` from the array, convert it to an `Integer` object, extract its value as `byte`, followed by boxing it into a `Byte`. It’s much simpler to use just `.mapToObj(idx -> data[idx])`, which reads a `byte` from the array and boxes it into a `Byte`. – Holger Jul 07 '18 at 13:31
2

Collecting to a byte array is not straight with Java 8.
But by using ByteArrayOutputStream::new as supplier in the collect operation you can.
It is a little more verbose because of the checked exception handling in the body lambda because of the combiner but it also has some advantages : it doesn't perform any boxing byte to Byte and it doesn't create unnecessary variables.

byte[] data = "y\neahbabydoit\nsothisistheway\ntodoit".getBytes();
byte[] dest = IntStream.range(0, data.length)
                       .map(i -> data[i])
                       .filter(i -> i != 10)
                       .collect(ByteArrayOutputStream::new, ByteArrayOutputStream::write, (bos1, bos2) -> {
                           try {
                               bos2.writeTo(bos1);
                           } catch (IOException e) {
                              throw new RuntimeException(e);
                           }
                       })
                       .toByteArray();

System.out.println("src:" + Arrays.toString(data));
System.out.println("dst:" + Arrays.toString(dest));

Output :

src:[121, 10, 101, 97, 104, 98, 97, 98, 121, ...]

dst:[121, 101, 97, 104, 98, 97, 98, 121,...]

davidxxx
  • 115,998
  • 20
  • 192
  • 199
  • 2
    You don’t need the type cast in `(bos, i) -> bos.write((byte) i)`, so you could even use `ByteArrayOutputStream::write`… – Holger Jul 09 '18 at 11:14