[java] Java 8 람다 목록에서 요소 가져 오기 및 제거
요소의 목록을 감안할 때, 나는 주어진 속성 요소를 싶어 하고 목록에서 제거합니다. 내가 찾은 최고의 솔루션은 다음과 같습니다.
ProducerDTO p = producersProcedureActive
.stream()
.filter(producer -> producer.getPod().equals(pod))
.findFirst()
.get();
producersProcedureActive.remove(p);
람다 식에서 get과 remove를 결합 할 수 있습니까?
답변
목록에서 요소를 제거하려면
objectA.removeIf(x -> conditions);
예 :
objectA.removeIf(x -> blockedWorkerIds.contains(x));
List<String> str1 = new ArrayList<String>();
str1.add("A");
str1.add("B");
str1.add("C");
str1.add("D");
List<String> str2 = new ArrayList<String>();
str2.add("D");
str2.add("E");
str1.removeIf(x -> str2.contains(x));
str1.forEach(System.out::println);
출력 :
A B C
답변
스레드가 꽤 오래되었지만 여전히 솔루션을 제공하는 것으로 생각됩니다 Java8
.
removeIf
기능을 사용하십시오 . 시간 복잡성은O(n)
producersProcedureActive.removeIf(producer -> producer.getPod().equals(pod));
API 참조 : removeIf 문서
가정은 : producersProcedureActive
A는List
참고 :이 접근 방식을 사용하면 삭제 된 항목을 유지할 수 없습니다.
답변
바닐라 자바 반복기를 사용하여 작업을 수행하는 것이 좋습니다.
public static <T> T findAndRemoveFirst(Iterable<? extends T> collection, Predicate<? super T> test) {
T value = null;
for (Iterator<? extends T> it = collection.iterator(); it.hasNext();)
if (test.test(value = it.next())) {
it.remove();
return value;
}
return null;
}
장점 :
- 분명하고 분명합니다.
- 일치하는 요소까지 한 번만 순회합니다.
- 지원
Iterable
없이도 할 수 있습니다 (적어도 반복기에서 구현 하는 사람들 ) .stream()
remove()
단점 :
- 단일 표현식으로 제자리에서 수행 할 수 없습니다 (보조 방법 또는 변수 필요).
에 관해서
람다 식에서 get과 remove를 결합 할 수 있습니까?
다른 답변은 가능하다는 것을 명확하게 보여 주지만
- 검색 및 제거는 목록을 두 번 탐색 할 수 있습니다.
ConcurrentModificationException
반복되는 목록에서 요소를 제거 할 때 throw 될 수 있습니다.
답변
직접적인 해결책은 ifPresent(consumer)
에서 반환 된 Optional 을 호출 하는 것 findFirst()
입니다. 이 소비자는 선택 사항이 비어 있지 않을 때 호출됩니다. 또한 현재 코드 에서처럼 find 작업이 빈 옵션을 반환하면 예외가 발생하지 않습니다. 대신 아무 일도 일어나지 않을 것입니다.
당신이 삭제 된 값을 반환 할 경우, 수 호출의 결과로 :map
Optional
remove
producersProcedureActive.stream()
.filter(producer -> producer.getPod().equals(pod))
.findFirst()
.map(p -> {
producersProcedureActive.remove(p);
return p;
});
그러나 remove(Object)
작업은 제거 할 요소를 찾기 위해 목록을 다시 탐색합니다. 와 같이 임의 액세스 권한이있는 목록이있는 경우 목록 ArrayList
의 인덱스에 대해 Stream을 만들고 술어와 일치하는 첫 번째 인덱스를 찾는 것이 좋습니다.
IntStream.range(0, producersProcedureActive.size())
.filter(i -> producersProcedureActive.get(i).getPod().equals(pod))
.boxed()
.findFirst()
.map(i -> producersProcedureActive.remove((int) i));
이 솔루션을 사용하면 remove(int)
작업이 인덱스에서 직접 작동합니다.
답변
사용은 Java 8의 필터를 사용할 수 있으며 이전 목록을 변경하지 않으려면 다른 목록을 만들 수 있습니다.
List<ProducerDTO> result = producersProcedureActive
.stream()
.filter(producer -> producer.getPod().equals(pod))
.collect(Collectors.toList());
답변
나는 이것이 인기없는 대답이 될 것이라고 확신하지만 작동합니다 …
ProducerDTO[] p = new ProducerDTO[1];
producersProcedureActive
.stream()
.filter(producer -> producer.getPod().equals(pod))
.findFirst()
.ifPresent(producer -> {producersProcedureActive.remove(producer); p[0] = producer;}
p[0]
발견 된 요소를 보유하거나 널이됩니다.
여기서 “트릭” 은 사실상 최종적인 배열 참조를 사용 하지만 첫 번째 요소를 설정 하여 “효과적으로 최종”문제를 우회하는 것입니다.
답변
함께 이클립스 컬렉션 당신이 사용할 수 detectIndex
와 함께 remove(int)
어떤 java.util.List를합니다.
List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int index = Iterate.detectIndex(integers, i -> i > 2);
if (index > -1) {
integers.remove(index);
}
Assert.assertEquals(Lists.mutable.with(1, 2, 4, 5), integers);
MutableList
Eclipse Collections 의 유형 을 사용하는 경우 detectIndex
목록에서 직접 메소드를 호출 할 수 있습니다 .
MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int index = integers.detectIndex(i -> i > 2);
if (index > -1) {
integers.remove(index);
}
Assert.assertEquals(Lists.mutable.with(1, 2, 4, 5), integers);
참고 : 저는 Eclipse 컬렉션의 커미터입니다.