Programing

Java 8 Streams가 컬렉션의 항목에서 작동 한 다음 제거 할 수 있습니까?

lottogame 2020. 11. 11. 07:51
반응형

Java 8 Streams가 컬렉션의 항목에서 작동 한 다음 제거 할 수 있습니까?


거의 모든 사람과 마찬가지로, 저는 여전히 새로운 Java 8 Streams API의 복잡성을 배우고 있습니다. 스트림 사용에 관한 질문이 있습니다. 간단한 예를 제공하겠습니다.

Java Streams를 사용하면를 가져 와서 모든 요소의 스트림을 수신 Collection하기 위해 stream()메서드를 사용할 수 있습니다. 그것은 내 유용 등의 방법이 될 것입니다 filter(), map()그리고 forEach()우리가 내용에 람다 연산을 사용할 수 있습니다.

다음과 같은 코드가 있습니다 (단순화 됨).

set.stream().filter(item -> item.qualify())
    .map(item -> (Qualifier)item).forEach(item -> item.operate());
set.removeIf(item -> item.qualify());

아이디어는 특정 한정자와 일치하는 세트의 모든 항목을 매핑 한 다음이를 통해 작동하는 것입니다. 작업 후에는 더 이상 사용되지 않으므로 원래 세트에서 제거해야합니다. 코드는 잘 작동하지만 Stream, 나를 위해 한 줄로이 작업을 수행 할 수 있는 작업이 있다는 느낌을 떨칠 수 없습니다 .

Javadocs에 있다면 간과 할 수 있습니다.

API에 더 익숙한 사람이 그런 것을 보나요?


다음과 같이 할 수 있습니다.

set.removeIf(item -> {
    if (!item.qualify())
        return false;
    item.operate();
    return true;
});

경우 item.operate()항상 반환 true당신은 매우 간결 할 수 있습니다.

set.removeIf(item -> item.qualify() && item.operate());

그러나 나는 무슨 일이 일어나고 있는지 즉시 명확하지 않기 때문에 이러한 접근 방식을 좋아하지 않습니다. 개인적으로 나는 이것을 위해 for루프와를 계속 사용할 것 Iterator입니다.

for (Iterator<Item> i = set.iterator(); i.hasNext();) {
    Item item = i.next();
    if (item.qualify()) {
        item.operate();
        i.remove();
    }
}

한 줄로 아니요,하지만 partitioningBy수집기를 사용할 수 있습니다 .

Map<Boolean, Set<Item>> map = 
    set.stream()
       .collect(partitioningBy(Item::qualify, toSet()));

map.get(true).forEach(i -> ((Qualifier)i).operate());
set = map.get(false);

세트를 두 번 반복하지 않기 때문에 더 효율적일 수 있습니다. 하나는 스트림 필터링 용이고 다른 하나는 해당 요소 제거 용입니다.

그렇지 않으면 귀하의 접근 방식이 비교적 괜찮다고 생각합니다.


많은 접근 방식이 있습니다. myList.remove (element)를 사용하는 경우 equals ()를 재정의해야합니다. 내가 선호하는 것은 :

allList.removeIf(item -> item.getId().equals(elementToDelete.getId()));

행운과 행복한 코딩 :)


작업 후에는 더 이상 사용되지 않으며 원래 세트에서 제거해야합니다. 코드는 잘 작동하지만 Stream에 한 줄로이 작업을 수행 할 수있는 작업이 있다는 느낌을 떨칠 수 없습니다.

스트림을 사용하여 스트림 소스에서 요소를 제거 할 수 없습니다. 로부터 자바 독 :

Most stream operations accept parameters that describe user-specified behavior..... To preserve correct behavior, these behavioral parameters:

  • must be non-interfering (they do not modify the stream source); and
  • in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).

What you really want to do is to partition your set. Unfortunately in Java 8 partitioning is only possible via the terminal "collect" method. You end up with something like this:

// test data set
Set<Integer> set = ImmutableSet.of(1, 2, 3, 4, 5);
// predicate separating even and odd numbers
Predicate<Integer> evenNumber = n -> n % 2 == 0;

// initial set partitioned by the predicate
Map<Boolean, List<Integer>> partitioned = set.stream().collect(Collectors.partitioningBy(evenNumber));

// print even numbers
partitioned.get(true).forEach(System.out::println);
// do something else with the rest of the set (odd numbers)
doSomethingElse(partitioned.get(false))

Updated:

Scala version of the code above

val set = Set(1, 2, 3, 4, 5)
val partitioned = set.partition(_ % 2 == 0)
partitioned._1.foreach(println)
doSomethingElse(partitioned._2)`

Nope, your implementation is probably the simplest one. You might do something deeply evil by modifying state in the removeIf predicate, but please don't. On the other hand, it might be reasonable to actually switch to an iterator-based imperative implementation, which might actually be more appropriate and efficient for this use case.


if I understand your question correctly:

set = set.stream().filter(item -> {
    if (item.qualify()) {
        ((Qualifier) item).operate();
        return false;
    }
    return true;
}).collect(Collectors.toSet());

I see Paul's clarity concern when using streams, stated in the top answer. Perhaps adding explaining variable clarifies intentions a little bit.

set.removeIf(item -> {
  boolean removeItem=item.qualify();
  if (removeItem){
    item.operate();
  }
  return removeItem;
});

참고URL : https://stackoverflow.com/questions/30041206/can-java-8-streams-operate-on-an-item-in-a-collection-and-then-remove-it

반응형