Java 8流。所有元素除了其他元素

时间:2016-02-19 18:23:30

标签: java java-8 java-stream

我有兴趣确定一种方法,该方法返回排除另一个列表中元素的元素列表。

例如

List<Integer> multiplesOfThree = ... // 3,6,9,12 etc
List<Integer> evens = ... // 2,4,6,8 etc
List<Integer> others = multiplesOfThree.except(evens) // should return a list of elements that are not in the other list
你怎么做的? 我找到了一种有点笨拙且难以阅读的方法......

multiplesOfThree.stream()
.filter(intval -> evens.stream().noneMatch(even -> even.intValue() == intval.intValue()))

3 个答案:

答案 0 :(得分:17)

您可以使用Stream's filter method,传递Predicate,以确保evens中的元素不存在。

List<Integer> others = multiplesOfThree.stream()
        .filter(i -> !evens.contains(i))
        .collect(Collectors.toList());

但假设您有一个可变的List(例如ArrayList),您甚至不需要流,只需Collections's removeAll method

multiplesOfThree.removeAll(evens);

答案 1 :(得分:6)

您可以使用

UIView *titleView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width - 88, 34)];
titleView.clipsToBounds = YES;

UIFont *titleFont = [UIFont systemFontOfSize:16 weight:UIFontWeightThin];
UIFont *speakerFont = [UIFont systemFontOfSize:10 weight:UIFontWeightLight];

CGSize speakerSize = [[self.speech speakerFullNameAndDate] sizeWithAttributes:@{ NSFontAttributeName : speakerFont }];
CGSize titleSize = [self.speech.title sizeWithAttributes:@{ NSFontAttributeName : titleFont }];

UILabel *titleLabel = [[UILabel alloc] init];
UILabel *subTitleLabel = [[UILabel alloc] init];

[titleView addSubview: titleLabel];
[titleView addSubview:subTitleLabel];

CGFloat titleDifference = (titleView.frame.size.width - titleLabel.frame.size.width) / 2;

titleLabel.text = self.speech.title;
titleLabel.font = titleFont;
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;

// titleLabel is bigger than the titleView's frame
if (titleSize.width > titleView.frame.size.width) {
    titleLabel.frame = CGRectMake(0, 0, titleView.frame.size.width - 20, 18);
} else {
    // titleDifference / 3 seems to be the best number for the frame's x coordinate
    titleLabel.frame = CGRectMake(titleDifference / 3, 0, titleSize.width, 18);
    [titleLabel sizeToFit];
}

subTitleLabel.text = [self.speech speakerFullNameAndDate];
subTitleLabel.font = speakerFont;
subTitleLabel.textAlignment = NSTextAlignmentCenter;
subTitleLabel.textColor = [UIColor whiteColor];
subTitleLabel.backgroundColor = [UIColor clearColor];
// Again, ((titleView.frame.size.width - speakerSize.width) / 3) seems to work best, though it's far from perfect
subTitleLabel.frame = CGRectMake(((titleView.frame.size.width - speakerSize.width) / 3), 20, speakerSize.width, 12);
[subTitleLabel sizeToFit];

self.navigationItem.titleView = titleView;

或更高效的大multipleOfThree.stream() .filter(((Predicate<Integer>) evens::contains).negate()) 列表

even

答案 2 :(得分:3)

有一些解决方案。

首先,不使用流,您只需创建一个新列表并从中删除其他集合中的所有元素......

final List<Integer> multiplesOfThree = Arrays.asList(3,6,9,12);
final List<Integer> evens = Arrays.asList(2,4,6,8,10,12);
final List<Integer> others1 = new ArrayList<>(multiplesOfThree);
others1.removeAll(evens);

另一种解决方案是将流传递给filter():

final List<Integer> others2 = multiplesOfThree
     .stream()
     .filter(x -> !evens.contains(x))
     .collect(Collectors.toList());

(在这种情况下,您可能需要考虑evensSet

最后,您可以修改上面的逻辑,将“evens”表示为函数,而不是所有偶数的集合。这基本上与上面相同,但您不必拥有第二个集合。

final List<Integer> others3 = multiplesOfThree
    .stream()
    .filter(x -> x % 2 != 0)
    .collect(Collectors.toList());