다른 목록에있는 개체의 속성으로 새 목록을 만드는 방법


81

특정 개체 목록이 있다고 상상해보십시오.

List<Student>

그리고 위 목록 의 idsof Students를 포함하여 다른 목록을 생성해야 합니다.

List<Integer>

루프를 사용하지 않고 아파치 컬렉션 이나 구아바를 사용하여이를 달성 할 수 있습니까?

제 경우에 어떤 방법이 유용해야합니까?


이봐, 난 지금 그것을 발견 : stackoverflow.com/questions/737244/...
Javatar

Jon의 대답은 꽤 멋지지만 살펴보면 루프도 사용합니다. 그것은 당신에게 표시되지 않을 수 있지만, 그러나 내부적으로는 것 - 모든 모든 솔루션은 루프를 사용합니다
HAGE

누군가 그것을 완료하기 위해 루프를 적용해야합니다. 당신 또는 당신이 사용할 수있는 lib.
sudmong

실제로 jon의 대답은 for 루프를 사용하고 싶지 않다는 점에서 내 상황에 맞지 않습니다. 나는 :)이 곳을 통해 더 편리한 방법입니다하지만 내가 그것을 찾기위한 기다리고 생각
Javatar

답변:


175

그것을하는 자바 8 방법 :-

List<Integer> idList = students.stream().map(Student::getId).collect(Collectors.toList());

2
튜플 목록을 원하면 어떻게합니까? [(Id, name), (Id, name)]과 같은 형식입니다.
Coder95

모든 Android API에 대해 모든 1.8 기능이 지원되는 것은 아닙니다. 특히 java.util.stream은 API 24까지 지원되지 않습니다.
The Black Horse

41

Guava를 사용하면 다음과 같은 기능을 사용할 수 있습니다.

private enum StudentToId implements Function<Student, Integer> {
        INSTANCE;

        @Override
        public Integer apply(Student input) {
            return input.getId();
        }
    }

이 기능을 사용하여 학생 목록을 다음과 같은 ID로 변환 할 수 있습니다.

Lists.transform(studentList, StudentToId.INSTANCE);

확실히 모든 ID를 추출하기 위해 반복되지만 guava 메서드는 view를 반환하고 Function은 반복 List<Integer>
하지 않으면 반복 을 시도 할 때만 적용됩니다 .

참고 : 이것이보기라는 것을 기억하고 여러 번 반복하려는 경우 다른 List<Integer>유사한 콘텐츠를 복사하는 것이 좋습니다.

ImmutableList.copyOf(Iterables.transform(students, StudentToId.INSTANCE));

함수를 따로 정의해야하는 것은 부적절하다고 생각합니다. 익명으로도 한 단계로 처리 할 수 ​​있다고 생각합니다
Marc

List의 문자열 (float 등) 멤버를 어떻게 추출합니까?
sepehr

22

Premraj 덕분에대체 멋진 옵션에 대한 에게 .

나는 아파치 CollectionUtils와 BeanUtils를 사용했습니다. 따라서 다음 코드의 성능에 만족합니다.

List<Long> idList = (List<Long>) CollectionUtils.collect(objectList, 
                                    new BeanToPropertyValueTransformer("id"));

위에서 사용한 guava ( Premraj 제공)와 collectionUtils 의 성능을 비교 하고 더 빠른 것을 결정할 것입니다.


3
나는 성능에 관계없이 아파치 컬렉션보다 구아바를 선호 할 것입니다.-더 현대적, 제네릭, 변형을위한 반사를 사용하지 않는 등의 이유로 전체 구아바는 아파치 컬렉션보다 훨씬 더 현대적입니다. 여기에서
Premraj

1
예, 그러나 실제로 변환하려는 각 유형의 객체에 대해 추가 열거 형 선언이 필요하기 때문에 사용을 제한하는 것은 좋은 생각이 아닙니다.
Javatar

그것은 당신의 디자인에 달려 있습니다-당신 IdentifiablegetId()방법 을 정의 하는 인터페이스를 가질 수 있으며이 단일 열거 형 단일 패턴을 사용하여 Id를 일반적으로 추출 할 수 있습니다.
Premraj 2012-06-12

2
구아바는 나중에 리플렉션을 사용하기 때문에 Bean 유틸리티보다 확실히 더 효율적입니다 ..
ravi

2
생성자 new BeanToPropertyValueTransformer ( "id")에서 속성 이름을 문자열로 사용하는 것은 확실히 피하려고하는 것입니다. 리팩토링은 어려울 것입니다! 하지만이 문제를 해결할 수있는 솔루션을 찾고 있습니다. 한편, 나는 장황하지만 안전한 Guava 솔루션을 사용할 것입니다.
redochka 2015 년

7

자바 8 람다 표현 솔루션 :

List<Integer> iDList = students.stream().map((student) -> student.getId()).collect(Collectors.toList());

Java 1.8 미만이면 Apache CollectionUtils를 사용하십시오. 예 : Collection <String> firstnames = CollectionUtils.collect (userlist, TransformerUtils.invokerTransformer ( "getFirstname"));
a_subscriber

5

몇 년 후에 누군가 여기에 오면 :

List<String> stringProperty = (List<String>) CollectionUtils.collect(listOfBeans, TransformerUtils.invokerTransformer("getProperty"));

그리고 당신은 단지 :) 나에게 저장
Behrad3d

-5

루프없이이를 수행하는 것은 수학적으로 불가능합니다. 불연속 값 집합의 매핑 F를 다른 불연속 값 집합에 매핑하려면 F가 원래 집합의 각 요소에 대해 작동해야합니다. (기본적으로이를 수행하려면 루프가 필요합니다.)

즉,

새 목록이 필요한 이유는 무엇입니까? 잘못된 방식으로 해결중인 문제에 접근 할 수 있습니다.

목록이있는 Student경우이 목록을 반복 할 때 학생의 ID 번호를 반복 할 때 한두 단계 만 남았습니다.

for(Student s : list)
{
    int current_id = s.getID();
    // Do something with current_id
}

다른 종류의 문제가있는 경우 질문에 댓글을 달거나 업데이트하면 도와 드리겠습니다.


먼저 답장을 보내 주셔서 감사합니다. 그러나 새 목록이 필요한 것이 잘못된 방법이라고 말한 것은 극적입니다. 필요한 용량과 범위에 따라 다르기 때문입니다. 따라서, 당신의 접근 방식은 잘못된 방법입니다 :) "루프없이 달성 할 수있는 능력"에 대한 저의 언급은 코드를 읽을 수없고 성능이 저하되지 않도록하는 더 편리한 방법에 관한 것입니다. 어쨌든, 나는 그것을 달성하는 방법을 이미 찾았고, 조금 나눌 것입니다.
Javatar

나는 그것을 말하지 않았다 입니다 길을 잘못하지만, 당신이 해결하려고하는 문제에 따라, 길을 잘못합니다.
Zéychin 2012-06-11
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.