IT이야기

Java List.contains(필드 값이 x와 동일한 개체)

cyworld 2022. 7. 12. 21:45
반응형

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>에는 를 contains contains a a가 되어 있습니다.MyObject는 with with with with with with with with 라는 이름으로name 에 하는 경우MyObject를 참조해 주세요.getName().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에서 제안하는 바와 같이, 「MK10」()Stream#anyMatch★★★★

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

두 가지 선택이 있습니다.

1. 오브젝트 클래스의 "equals()" 메서드를 덮어쓰는 것이 바람직합니다.

예를 들어 다음과 같은 오브젝트 클래스가 있다고 합시다.

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

이제 MyObject 이름에만 관심이 있다고 칩시다.MyObject 이름이 고유해야 합니다.그러면 두 개의 MyObject가 같은 이름을 가지고 있으면 동일한 이름으로 간주됩니다.이 경우 이름을 비교하여 동등성을 판단하도록 'equals' 메서드(및 'hashcode' 메서드)를 덮어쓸 수 있습니다.

이렇게 하면 다음과 같이 컬렉션에 "foo"라는 이름의 MyObject가 포함되어 있는지 확인할 수 있습니다.

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

단, 다음과 같은 경우에는 이 옵션이 적용되지 않을 수 있습니다.

  • 이름과 위치를 모두 사용하여 동일성을 확인하지만 컬렉션에 특정 위치를 가진 "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;
    }

불행하게도 더 나은 방법은 없다.

Java 8+ 를 사용하는 방법은 다음과 같습니다.

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

구글 구아바

Guava를 사용하는 경우 기능적으로 접근하여 다음을 수행할 수 있습니다.

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

에 검색마다 할 수 .그러나 술어는 개체이므로 검색마다 다른 변형을 제공할 수 있습니다.라이브러리 자체가 컬렉션의 반복과 적용하려는 함수를 어떻게 구분하는지 주목하십시오. 덮어쓸 는 없습니다.equals()특정 행동에 대한 것입니다.

다음과 같이 java.util.Java 8 이상에 내장된 스트림 프레임워크는 유사한 기능을 제공합니다.

Collection.contains()합니다.equals()될 때까지 각 true.

이것을 중 는 우선으로 하는 입니다.equals()이치

따라서 Guava와 같은 프레임워크는 이에 대해 술어를 사용합니다.와 함께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());

이런 걸 신경 쓴다면 '자바를 넘어서'라는 책을 추천해요.자바의 수많은 단점들과 다른 언어들이 어떻게 더 잘 할 수 있는지에 대한 많은 예들이 포함되어 있다.

바이너리 검색

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가 됩니다.

이클립스 컬렉션

Eclipse 컬렉션을 사용하는 경우anySatisfy()이렇게 하다, , 쓰다, 쓰다, 쓰다, 쓰다, 하다.Listin a a a a ListAdapter 바꿀 수도 요.ListListIterable가능하면.

ListIterable<MyObject> list = ...;

boolean result =
    list.anySatisfy(myObject -> myObject.getName().equals("John"));

이러한 작업을 자주 수행할 경우 유형에 속성이 있는지 여부를 응답하는 메서드를 추출하는 것이 좋습니다.

public class MyObject
{
    private final String name;

    public MyObject(String name)
    {
        this.name = name;
    }

    public boolean named(String name)
    {
        return Objects.equals(this.name, name);
    }
}

할 수 있습니다.anySatisfyWith()메서드 참조와 함께.

boolean result = list.anySatisfyWith(MyObject::named, "John");

변경할 수 없는 경우ListListIterable를 사용하는 방법은 다음과 같습니다.ListAdapter.

boolean result = 
    ListAdapter.adapt(list).anySatisfyWith(MyObject::named, "John");

주의: 저는 이클립스 선정의 커밋자입니다.

Predicate

Java 8 또는 컬렉션을 처리하는 데 더 많은 기능을 제공하는 라이브러리를 사용하지 않으면 솔루션보다 더 재사용 가능한 기능을 구현할 수 있습니다.

interface Predicate<T>{
        boolean contains(T item);
    }

    static class CollectionUtil{

        public static <T> T find(final Collection<T> collection,final  Predicate<T> predicate){
            for (T item : collection){
                if (predicate.contains(item)){
                    return item;
                }
            }
            return null;
        }
    // and many more methods to deal with collection    
    }

저는 이런 것을 사용하고 있습니다. 술어 인터페이스를 가지고 있고, 그것을 구현한 것을 util 클래스에 전달하고 있습니다.

내 방식대로 하면 어떤 이점이 있습니까?모든 유형의 컬렉션에서 검색을 처리하는 한 가지 방법이 있습니다.다른 필드로 검색하려면 별도의 메서드를 작성할 필요가 없습니다.필요한 것은 다른 술어를 지정하는 것입니다.이 술어는 더 이상 쓸모가 없어지면 바로 파기될 수 있습니다.

만약 당신이 그것을 사용하고 싶다면, 당신이 해야 할 모든 것은 호출 방식을 정의하고 tyour 술어를 정의하는 것입니다.

CollectionUtil.find(list, new Predicate<MyObject>{
    public boolean contains(T item){
        return "John".equals(item.getName());
     }
});

여기 Guava를 사용한 솔루션이 있습니다.

private boolean checkUserListContainName(List<User> userList, final String targetName){

    return FluentIterable.from(userList).anyMatch(new Predicate<User>() {
        @Override
        public boolean apply(@Nullable User input) {
            return input.getName().equals(targetName);
        }
    });
}

contains메서드 사용equals내부적으로그래서 넌 이 모든 걸 덮어쓸 필요가 있어equals당신의 필요에 따라 당신의 수업을 위한 방법.

그러나 이것은 구문적으로 정확해 보이지 않습니다.

new Object().setName("John")

이 작업을 수행해야 하는 경우List.contains(Object with field value equal to x)단순하고 효율적인 회피책은 다음과 같습니다.

List<field obj type> fieldOfInterestValues = new ArrayList<field obj type>;
for(Object obj : List) {
    fieldOfInterestValues.add(obj.getFieldOfInterest());
}

그 다음에List.contains(Object with field value equal to x)같은 결과를 얻을 수 있다fieldOfInterestValues.contains(x);

JAVA 8 SDK에도 불구하고 http://commons.apache.org/proper/commons-collections/과 같은 많은 수집 도구가 있습니다.

Predicate condition = new Predicate() {
   boolean evaluate(Object obj) {
        return ((Sample)obj).myField.equals("myVal");
   }
};
List result = CollectionUtils.select( list, condition );

언급URL : https://stackoverflow.com/questions/18852059/java-list-containsobject-with-field-value-equal-to-x

반응형