2016-04-08 76 views
17

我可以做转换的代码是这样的:转换一个对象[]布尔值的布尔[]使用流

Object[] array = (Object[]) message.get(key); 
boolean[] result = new boolean[array.length]; 
for (int i = 0; i < array.length; i++) { 
    result[i] = (boolean) array[i]; 
} 

但是,我认为这是可以做到使用Java 8相同的转换流。我开始编写这样的代码:

boolean[] = Arrays.stream(array) 
        .map(Boolean.class::cast) 
        .map(Boolean::booleanValue) 
        .toArray() 

但是这段代码不起作用。编译器说

incompatible types: java.lang.Object[] cannot be converted to boolean[] 

我想了解代码的问题是什么。我认为map(Boolean::booleanValue)会返回一个我可以通过toArray收集的布尔值流。

+2

这是行不通的,因为'Object []'和'boolean []'是Java中不可转换的类型,所以实际上'Object [] = boolean []'也不起作用。 – Jagger

+2

'.toArray()'这里是通用的,所以'Object []'是最好的。你可以编写你自己的收集器来返回'boolean []'。 –

+0

@SashaSalauyou然而你可以使用'toArray(IntFunction generator)'来返回一个类型数组。我加了一个答案作为例子。 –

回答

15

没有,因为map(Boolean::booleanValue)扩大到

map((Boolean value) -> (Boolean)value.booleanValue()); 

(注意自动装箱由编译器插入,因为传递给map()函数必须返回一个Object,而不是一个boolean

这就是为什么Java8流包括一大堆专门的类(IntStream,LongStreamDoubleStream)。可悲的是,boolean没有专门的流类。

8

如果你不反对得到一个列表,而不是想法,你可以简单地进行collect作为终端动作:

final List<Boolean> boolList = Arrays.stream(array) 
            .map(Boolean.class::cast) 
            .map(Boolean::booleanValue) 
            .collect(Collectors.toList()); 

这里定义的流仅能如果你产生Object[]的尝试将其收集到一个数组中。使用列表至少可以让您保持想要将其转换为的类型。

+0

只是出于好奇,以后如果他们真的想把OP列表转换成布尔数组, –

+2

@JeelShah:是的,但他们可以得到一个布尔[],而不是'布尔[]'。如果OP想要'boolean []',他们就不得不做更多的工作。 – Makoto

+0

啊,好吧。感谢您的额外信息! –

4

我认为值得注意的是,有一个toArray(IntFunction<A[]> generator)至少可以让您得到Boolean[]的最终结果,它更接近您想要的结果。

Boolean[] boolArray = Arrays.stream(array) 
       .map(Boolean.class::cast) 
       .map(Boolean::booleanValue) 
       .toArray(Boolean[]::new); 
5

原始类型的唯一流是IntStreamLongStreamDoubleStream。特别是没有BooleanStream,并且没有将Stream<Boolean>转换为boolean[]的惯用方法。

如果需要此功能,经常可以使用一个实用程序类是这样的:

public final class BooleanUtils { 

    private BooleanUtils() {} 

    public static boolean[] listToArray(List<Boolean> list) { 
     int length = list.size(); 
     boolean[] arr = new boolean[length]; 
     for (int i = 0; i < length; i++) 
      arr[i] = list.get(i); 
     return arr; 
    } 

    public static final Collector<Boolean, ?, boolean[]> TO_BOOLEAN_ARRAY 
     = Collectors.collectingAndThen(Collectors.toList(), BooleanUtils::listToArray); 
} 

然后,给出一个Stream<Boolean>,你将能够做到:

boolean[] arr = stream.collect(BooleanUtils.TO_BOOLEAN_ARRAY); 
2

Java基本类型AREN因此您不能直接将Boolean转换为boolean(在Java 1.5中已将autoboxing and unboxing添加到语言中,并且不对包装类型的数组使用原始类型)。但是,你可以使用一个IntStream.range(int, int)

boolean[] result = new boolean[array.length]; 
IntStream.range(0, array.length).forEach(x -> result[x] = (boolean) array[x]); 
2

在我的免费StreamEx库有一个收藏家toBooleanArray它创建了一个原始的布尔数组:

boolean[] result = Arrays.stream(array) 
         .collect(MoreCollectors.toBooleanArray(obj -> (boolean)obj)); 

如果你不喜欢使用第三方库你可以自己实现这样的收集器:

public static <T> Collector<T, ?, boolean[]> toBooleanArray(Predicate<? super T> predicate) { 
    class Acc { 
     BitSet bs = new BitSet(); 
     int count = 0; 
    } 
    return Collector.of(Acc::new, (acc, t) -> acc.bs.set(acc.count++, predicate.test(t)), 
      (acc1, acc2) -> { 
       acc2.bs.stream().forEach(i -> acc1.bs.set(i + acc1.count)); 
       acc1.count += acc2.count; 
       return acc1; 
      }, acc -> { 
       boolean[] res = new boolean[acc.count]; 
       acc.bs.stream().forEach(i -> res[i] = true); 
       return res; 
      }); 
} 

它适用于顺序和并行流并退出e记忆友好。