Java List. contains (필드 값이 x 인 객체) 효율적인 코드가 있는지

List특정 값을 가진 필드가있는 객체가 포함되어 있는지 확인하고 싶습니다 . 이제 루프를 사용하여 확인하고 더 효율적인 코드가 있는지 궁금했습니다.

같은 것;

if(list.contains(new Object().setName("John"))){
    //Do some stuff
}

위의 코드는 아무것도하지 않는다는 것을 알고 있습니다. 단지 달성하려는 것을 대략 보여줍니다.

또한 명확히하기 위해 간단한 루프를 사용하지 않으려는 이유는이 코드가 현재 루프 내부의 루프 내부에있는 루프 내부에 있기 때문입니다. 가독성을 위해 루프에 루프를 계속 추가하고 싶지 않습니다. 그래서 간단한 대안이 있는지 궁금했습니다.



답변

스트림

Java 8을 사용하는 경우 다음과 같이 시도해 볼 수 있습니다.

public boolean containsName(final List<MyObject> list, final String name){
    return list.stream().filter(o -> o.getName().equals(name)).findFirst().isPresent();
}

또는 다음과 같이 시도해 볼 수 있습니다.

public boolean containsName(final List<MyObject> list, final String name){
    return list.stream().map(MyObject::getName).filter(name::equals).findFirst().isPresent();
}

이 메소드는 에 이름 trueList<MyObject>포함되어 있으면를 반환 합니다 . s 각각에 대해 작업을 수행하려면 다음과 같이 시도하십시오.MyObjectnameMyObjectgetName().equals(name)

public void perform(final List<MyObject> list, final String name){
    list.stream().filter(o -> o.getName().equals(name)).forEach(
            o -> {
                //...
            }
    );
}

여기서 인스턴스를 o나타냅니다 MyObject.

또는 의견에서 알 수 있듯이 (감사 MK10) 다음 Stream#anyMatch방법을 사용할 수 있습니다 .

public boolean containsName(final List<MyObject> list, final String name){
    return list.stream().anyMatch(o -> o.getName().equals(name));
}


답변

두 가지 선택이 있습니다.

1. 가장 바람직한 방법은 Object 클래스에서`equals ()`메서드를 재정의하는 것입니다.

예를 들어이 Object 클래스가 있다고 가정 해 보겠습니다.

public class MyObject {
    private String name;
    private String location;
    //getters and setters
}

이제 MyObject의 이름에만 관심이 있다고하자. 고유 한 이름이어야하므로 두 개의 MyObject 이름이 같은 경우 동일하다고 간주해야합니다. 이 경우 이름을 비교하여 동등성을 결정하기 위해`equals ()`메소드 (및`hashcode ()`메소드)를 대체하려고합니다.

이 작업을 완료하면 Collection에 이름이 “foo”인 MyObject가 포함되어 있는지 확인할 수 있습니다.

MyObject object = new MyObject();
object.setName("foo");
collection.contains(object);

그러나 다음과 같은 경우에는이 옵션이 적합하지 않을 수 있습니다.

  • 이름과 위치를 모두 사용하여 동등성을 확인하고 있지만 Collection에 특정 위치의 MyObject가 있는지 확인하려고합니다. 이 경우 이미 ‘equals ()’를 재정의했습니다.
  • `MyObject`는 자유롭게 변경할 수없는 API의 일부입니다.

이 중 하나에 해당하면 옵션 2를 원할 것입니다.

2. 자신 만의 유틸리티 메소드를 작성하십시오.

public static boolean containsLocation(Collection<MyObject> c, String location) {
    for(MyObject o : c) {
        if(o != null && o.getLocation.equals(location)) {
            return true;
        }
    }
    return false;
}

또는 ArrayList (또는 다른 컬렉션)를 확장 한 다음 고유 한 메서드를 추가 할 수 있습니다.

public boolean containsLocation(String location) {
    for(MyObject o : this) {
        if(o != null && o.getLocation.equals(location)) {
                return true;
            }
        }
        return false;
    }

불행히도 그 주위에 더 좋은 방법은 없습니다.


답변

구글 구아바

Guava를 사용 하는 경우 기능적인 접근 방식을 취하고 다음을 수행 할 수 있습니다.

FluentIterable.from(list).find(new Predicate<MyObject>() {
   public boolean apply(MyObject input) {
      return "John".equals(input.getName());
   }
}).Any();

조금 장황하게 보입니다. 그러나 술어는 오브젝트이며 다른 검색에 대해 다른 변형을 제공 할 수 있습니다. 라이브러리 자체가 컬렉션의 반복과 적용하려는 기능을 분리하는 방법에 유의하십시오. equals()특정 행동 을 무시할 필요가 없습니다 .

아래에 언급 된 바와 같이, Java 8 이상에 내장 된 java.util.Stream 프레임 워크는 유사한 것을 제공합니다.


답변

다음은 Java 8 이상을 사용하는 방법입니다.

boolean isJohnAlive = list.stream().anyMatch(o -> o.getName().equals("John"));


답변

Collection.contains()equals()하나가 반환 될 때까지 각 개체 를 호출 하여 구현됩니다 true.

따라서 이것을 구현하는 한 가지 방법은 재정의하는 equals()것이지만 물론 하나만 가질 수 있습니다.

따라서 구아바 와 같은 프레임 워크 는이를 위해 술어를 사용합니다. 을 사용 Iterables.find(list, predicate)하면 테스트를 술어에 넣어 임의의 필드를 검색 할 수 있습니다.

VM 위에 빌드 된 다른 언어에는이 언어가 내장되어 있습니다. 예를 들어 Groovy 에서는 다음과 같이 작성하면됩니다.

def result = list.find{ it.name == 'John' }

Java 8은 우리의 삶을 더 편하게 만들었습니다.

List<Foo> result = list.stream()
    .filter(it -> "John".equals(it.getName())
    .collect(Collectors.toList());

이런 것들에 관심이 있다면 “Beyond Java”책을 제안합니다. 여기에는 수많은 Java 단점과 다른 언어의 성능에 대한 많은 예가 포함되어 있습니다.


답변

이진 검색

Collections.binarySearch 를 사용 하여 목록에서 요소를 검색 할 수 있습니다 (목록이 정렬되어 있다고 가정).

Collections.binarySearch(list, new YourObject("a1", "b",
                "c"), new Comparator<YourObject>() {

            @Override
            public int compare(YourObject o1, YourObject o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

컬렉션에 개체가 없으면 음수를 반환하거나 그렇지 않으면 index개체의 개체를 반환 합니다. 이를 통해 검색 전략이 다른 객체를 검색 할 수 있습니다.


답변

지도

당신은 만들 수 있습니다 Hashmap<String, Object>키로 값의 사용을, 그리고이라면 보는 yourHashMap.keySet().contains(yourValue)true를 반환합니다.