2017-05-19 2 views
4

나는 다음과 같은 코드가 있습니다 :자바로 findFirst()의 인덱스를 얻는 방법 8

내가 ArrayList와 항목의 내부를 편집해야하기 때문에 첫 번째 반환 요소의 인덱스가 무엇인지 알 필요가
ArrayList <String> entries = new ArrayList <String>(); 

entries.add("0"); 
entries.add("1"); 
entries.add("2"); 
entries.add("3"); 

String firstNotHiddenItem = entries.stream() 
        .filter(e -> e.equals("2")) 
        .findFirst() 
        .get(); 

. 내가 아는 한 get()은 참조가 아닌 요소의 값을 반환합니다. 방금 사용해야합니까

int indexOf(Object o) 

대신에 사용해야합니까?

int index = IntStream.range(0, entries.size()) 
        .filter(i -> "2".equals(entries.get(i))) 
        .findFirst().orElse(-1); 

을하지만 더 표현,보다 간결이고 동일한 결과를 계산하기 때문에 당신이 선호하는 방법입니다 List::indexOf 방법을 사용한다 :

답변

2

할 수 있습니다하지 간단한 방법으로 - 그들이 스트림에있는 곳의 상황이없는 스트림 프로세스 요소. 그러나

, 당신은 장갑을 벗을 준비가 있다면 ...

int[] position = {-1}; 

String firstNotHiddenItem = entries.stream() 
     .peek(x -> position[0]++) // increment every element encounter 
     .filter("2"::equals) 
     .findFirst() 
     .get(); 

System.out.println(position[0]); // 2 

대신 간단한 intint[]의 사용은은 "효과적으로 최종"요구 사항을 회피하는 것입니다; 어레이에 대한 참조상수이고, 그 중 내용은입니다. 또한

참고 가능한 NPE을 피할뿐만 아니라, 방법 참조 "2"::equals 대신 람다 e -> e.equals("2")의 용도 (스트림 소자 null 인 경우) 더 중요한 방법 쿨러 보인다.


더 맛 (이하 hackalicious) 버전 :

AtomicInteger position = new AtomicInteger(); 

String firstNotHiddenItem = entries.stream() 
     .peek(x -> position.incrementAndGet()) // increment every element encounter 
     .filter("2"::equals) 
     .findFirst() 
     .get(); 

position.get(); // 2 
+0

완벽한 답변! 간단하고 우아하고 정확히 내가 뭘 찾고 있었습니까! 감사! – Andrei

4

당신은 IntStream 등을 사용하여 요소의 인덱스를 얻을 수 있습니다. 다음과 같이

+2

'List.indexOf'와'filter'와'findFirst'를 사용하는 스트림의 주요 차이점은'indexOf'는리스트 요소의 클래스의'equals' 메소드를 사용한다는 것입니다. 당신은 원소의 * 평등 *과 관련이없는 잠재적 인 복잡한 술어를 기반으로 검색해야합니다. –

0

당신이 MutableList를 사용하는 경우이 자바 8

int firstIndex = ListIterate.detectIndex(entries, "2"::equals); 

Eclipse Collections를 사용하여 작동합니다, 당신은 코드를 단순화 할 수 있습니다 또한 마지막 인덱스를 찾을 수있는 방법이있다

MutableList<String> entries = Lists.mutable.with("0", "1", "2", "3"); 
int firstIndex = entries.detectIndex("2"::equals); 

.

int lastIndex = entries.detectLastIndex("2"::equals); 

참고 : 나는 이클립스 컬렉션의 커미터이다

0

예, 대신 indexOf("2")를 사용해야합니다. 이미 알았 듯이 스트림 기반 솔루션은 어떤 이점도 제공하지 않고 복잡성이 더 큽니다.

이 특정 상황에서는 성능에 큰 차이가 없지만 스트림을 과도하게 사용하면 성능이 크게 저하 될 수 있습니다. map.get(object) 대신 map.entrySet().stream().filter(e -> e.getKey().equals(object)).map(e -> e.getValue())을 사용하는 경우

수집 작업은 알려진 구조를 활용할 수 있지만 대부분의 스트림 작업은 선형 검색을 의미합니다. 따라서 진짜 수집 작업이 바람직합니다.

물론 술어가 간단한 동등성 테스트가 아닌 것처럼 수집 작업이없는 경우 스트림 API가 올바른 도구 일 수 있습니다. "Is there a concise way to iterate over a stream with indices in Java 8?"에 표시된 것처럼 인덱스를 포함하는 모든 작업에 대한 솔루션은 인덱스를 시작점으로 사용하여 작동합니다. IntStream.range을 통해 수신하고 List.get(int)을 통해 목록에 액세스합니다. 배열 또는 무작위 액세스가 아닌 소스가 List 인 경우 똑같이 깨끗하고 효율적인 솔루션이 없습니다. 때로는 루프가 가장 간단하고 효율적인 솔루션이 될 수도 있습니다.