Java 8 람다 목록에서 요소 가져 오기 및 제거
요소의 목록을 감안할 때, 나는 주어진 속성 요소를 싶어 하고 목록에서 제거합니다. 내가 찾은 최고의 솔루션은 다음과 같습니다.
ProducerDTO p = producersProcedureActive
.stream()
.filter(producer -> producer.getPod().equals(pod))
.findFirst()
.get();
producersProcedureActive.remove(p);
람다 식에서 get과 remove를 결합 할 수 있습니까?
목록에서 요소를 제거하려면
objectA.removeIf (x-> 조건);
예 : 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);
출력 : ABC
스레드가 꽤 오래되었지만 여전히 솔루션을 제공하는 것으로 생각됩니다 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 컬렉션의 커미터입니다.
다른 사람들이 제안했듯이 이것은 루프와 이터 러블의 사용 사례 일 수 있습니다. 제 생각에는 이것이 가장 간단한 접근 방식입니다. 목록을 제자리에서 수정하려는 경우 어쨌든 "실제"함수 프로그래밍으로 간주 할 수 없습니다. 그러나 Collectors.partitioningBy()
조건을 충족하는 요소가있는 새 목록과 그렇지 않은 요소의 새 목록을 얻기 위해 사용할 수 있습니다 . 물론이 접근 방식을 사용하면 조건을 충족하는 여러 요소가있는 경우 첫 번째 요소뿐만 아니라 모든 요소가 해당 목록에 포함됩니다.
아래 논리는 원래 목록을 수정하지 않고 해결책입니다.
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");
List<String> str3 = str1.stream()
.filter(item -> !str2.contains(item))
.collect(Collectors.toList());
str1 // ["A", "B", "C", "D"]
str2 // ["D", "E"]
str3 // ["A", "B", "C"]
내 초기 아이디어와 답변을 결합하여 내 질문에 대한 해결책으로 보이는 것에 도달했습니다.
public ProducerDTO findAndRemove(String pod) {
ProducerDTO p = null;
try {
p = IntStream.range(0, producersProcedureActive.size())
.filter(i -> producersProcedureActive.get(i).getPod().equals(pod))
.boxed()
.findFirst()
.map(i -> producersProcedureActive.remove((int)i))
.get();
logger.debug(p);
} catch (NoSuchElementException e) {
logger.error("No producer found with POD [" + pod + "]");
}
return p;
}
It lets remove the object using remove(int)
that do not traverse again the list (as suggested by @Tunaki) and it lets return the removed object to the function caller.
I read your answers that suggest me to choose safe methods like ifPresent
instead of get
but I do not find a way to use them in this scenario.
Are there any important drawback in this kind of solution?
Edit following @Holger advice
This should be the function I needed
public ProducerDTO findAndRemove(String pod) {
return IntStream.range(0, producersProcedureActive.size())
.filter(i -> producersProcedureActive.get(i).getPod().equals(pod))
.boxed()
.findFirst()
.map(i -> producersProcedureActive.remove((int)i))
.orElseGet(() -> {
logger.error("No producer found with POD [" + pod + "]");
return null;
});
}
When we want to get multiple elements from a List into a new list (filter using a predicate) and remove them from the existing list, I could not find a proper answer anywhere.
Here is how we can do it using Java Streaming API partitioning.
Map<Boolean, List<ProducerDTO>> classifiedElements = producersProcedureActive
.stream()
.collect(Collectors.partitioningBy(producer -> producer.getPod().equals(pod)));
// get two new lists
List<ProducerDTO> matching = classifiedElements.get(true);
List<ProducerDTO> nonMatching = classifiedElements.get(false);
// OR get non-matching elements to the existing list
producersProcedureActive = classifiedElements.get(false);
This way you effectively remove the filtered elements from the original list and add them to a new list.
Refer the 5.2. Collectors.partitioningBy section of this article.
the task is: get ✶and✶ remove element from list
p.stream().collect( Collectors.collectingAndThen( Collector.of(
ArrayDeque::new,
(a, producer) -> {
if( producer.getPod().equals( pod ) )
a.addLast( producer );
},
(a1, a2) -> {
return( a1 );
},
rslt -> rslt.pollFirst()
),
(e) -> {
if( e != null )
p.remove( e ); // remove
return( e ); // get
} ) );
참고URL : https://stackoverflow.com/questions/35701337/java-8-lambda-get-and-remove-element-from-list
'Program Tip' 카테고리의 다른 글
Virtualenv 샌드 박스에 PyQt4 / PySide 패키지를 추가 할 수 있습니까? (0) | 2020.12.06 |
---|---|
진행 대화 상자에서 취소 버튼을 설정하는 방법은 무엇입니까? (0) | 2020.12.06 |
Beanstalk : Node.js 배포-권한 거부로 인해 node-gyp 실패 (0) | 2020.12.06 |
WideCharToMultiByte를 올바르게 사용하는 방법 (0) | 2020.12.06 |
마우스 오른쪽 버튼 클릭에 이벤트 바인딩 (0) | 2020.12.06 |