programing

Java SE 8에는 페어 또는 튜플이 있습니까?

nicescript 2022. 8. 9. 22:09
반응형

Java SE 8에는 페어 또는 튜플이 있습니까?

Java SE 8에서 느린 기능 조작을 하고 있는데,map지표i한 쌍/태플에(i, value[i]),그리고나서filter두 번째에 의거하여value[i]마지막으로 인덱스만 출력합니다.

내가 아직도 이런 고통을 겪어야 하나요?Java에서의 C++ 페어<L,R>는 무엇입니까?람다와 개울의 대담한 새 시대에?

업데이트: 다음 답변 중 하나로 @dkatzel에서 제공하는 깔끔한 솔루션을 사용한 간단한 예를 제시했습니다.그러나 일반화가 되지 않습니다.따라서 보다 일반적인 예를 추가하겠습니다.

package com.example.test;

import java.util.ArrayList;
import java.util.stream.IntStream;

public class Main {

  public static void main(String[] args) {
    boolean [][] directed_acyclic_graph = new boolean[][]{
        {false,  true, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false, false}
    };

    System.out.println(
        IntStream.range(0, directed_acyclic_graph.length)
        .parallel()
        .mapToLong(i -> IntStream.range(0, directed_acyclic_graph[i].length)
            .filter(j -> directed_acyclic_graph[j][i])
            .count()
        )
        .filter(n -> n == 0)
        .collect(() -> new ArrayList<Long>(), (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2))
    );
  }

}

이로 인해 잘못된 출력이 생성됩니다.[0, 0, 0]세 열의 카운트에 대응합니다.false제가 필요한 것은 이 세 열의 색인입니다.올바른 출력은 다음과 같습니다.[0, 2, 4]어떻게 하면 이 결과를 얻을 수 있을까요?

업데이트: 이 답변은 "Java SE 8에 Pair 또는 Tuple이 있습니까?"라는 질문에 대한 답변입니다(그렇지 않다면 암묵적으로 왜 없습니까?).OP는 보다 완벽한 예시로 문제를 업데이트했지만, 어떤 종류의 Pair 구조도 사용하지 않고 해결할 수 있을 것 같습니다.[OP 메모: 여기 다른 정답이 있습니다]


간단한 대답은 '아니오'입니다.직접 롤업하거나 구현된 여러 라이브러리 중 하나를 가져와야 합니다.

가지고 있다PairJava SE의 클래스가 제안되어 적어도 한 번 거부되었습니다.OpenJDK 메일 목록 중 하나에서 이 토론 스레드를 참조하십시오.단점은 명확하지 않다.한편, 다른 라이브러리와 애플리케이션 코드에는 많은 Pair 구현이 있습니다.이는 필요성을 나타내며, Java SE에 이러한 클래스를 추가하면 재사용과 공유가 증가할 것입니다.한편, Pair 클래스가 있으면, 필요한 타입이나 추상화를 작성하지 않고 Pair와 컬렉션으로 복잡한 데이터 구조를 작성하려는 유혹을 더합니다(이것은 Kevin Bourillion의 메시지를 그 스레드에서 바꾸어 쓴 것입니다).

나는 모든 사람들이 그 이메일 스레드를 읽을 것을 추천한다.그것은 매우 통찰력 있고 화려하지 않다.꽤 설득력이 있어요.처음 시작할 때는 "Java SE에 Pair class가 있어야지"라고 생각했지만 스레드가 끝날 무렵에는 생각이 바뀌었습니다.

단, JavaFX에는 javafx.util이 있습니다.페어 클래스JavaFX의 API는 Java SE API와는 별도로 진화했습니다.

링크된 질문에서 알 수 있듯이 Java에서 C++ Pair와 동등한 것은 무엇입니까?외관상 단순한 API를 둘러싼 디자인 공간이 상당히 넓다.물체는 불변의 것이어야 하는가?시리얼화 가능해야 합니까?비교할 수 있어야 할까요?수업은 기말고사여야 할까요?두 요소를 주문해야 합니까?인터페이스 또는 클래스 중 어느 쪽이어야 합니까?왜 2인 1조로 멈추는 거죠?트리플, 쿼드, N-튜플은 어떨까요?

물론 자연에 따라 필연적으로 명명되는 자전거도 있습니다.

  • (a, b)
  • (첫 번째, 두 번째)
  • (왼쪽, 오른쪽)
  • (자동차, CDR)
  • (foo, 바)
  • 기타.

거의 언급되지 않은 하나의 큰 문제는 쌍과 원소의 관계이다.를 가지고 있는 경우(int x, int y)2D 공간의 한 점을 나타내는 기준, 이를 다음과 같이 나타냅니다.Pair<Integer, Integer>는 2개의 32비트 워드가 아닌3개의 오브젝트를 소비합니다.또한 이러한 개체는 힙에 있어야 하며 GC 오버헤드가 발생합니다.

Streams와 마찬가지로 Pairs에 대한 원시적인 전문화가 필수적이라는 것은 분명해 보입니다.보고 싶은 항목:

Pair
ObjIntPair
ObjLongPair
ObjDoublePair
IntObjPair
IntIntPair
IntLongPair
IntDoublePair
LongObjPair
LongIntPair
LongLongPair
LongDoublePair
DoubleObjPair
DoubleIntPair
DoubleLongPair
DoubleDoublePair

심지어...IntIntPair에는 여전히 힙에 하나의 개체가 필요합니다.

물론 이러한 것들은 네트워크 내의 기능 인터페이스의 확산을 연상시킵니다.java.util.function패키지가 포함되어 있습니다.더부룩한 API를 원하지 않는다면 어떤 API를 생략하시겠습니까?또, 이것만으로는 불충분하고, 예를 들면, 다음과 같은 전문화가 있다고 주장할 수도 있습니다.Boolean추가되어야 합니다.

Java가 오래 전에 Pair 클래스를 추가했다면 단순하거나 단순했을 것이고, 현재 우리가 구상하고 있는 많은 사용 사례를 충족하지 못했을 것입니다.JDK 1.0 시간대에 페어가 추가되었다면 아마 변경이 가능했을 것입니다.(java.util을 참조해 주십시오.날짜) 사람들이 좋아했을까요?Java에 Pair 클래스가 있다면 별로 쓸모가 없을 것 같습니다.또한 모든 사람이 자신의 요구를 만족시키기 위해 자신의 Pair와 Tuple을 사용하고 외부 라이브러리에는 다양한 Pair와 Tuple을 실장하고 있으며, Java의 Pair 클래스를 어떻게 수정해야 하는지에 대해서는 여전히 논쟁과 토론이 있을 것입니다.다시 말해, 우리가 지금 있는 곳과 같은 곳에 있는 셈이죠

한편, JVM(그리고 최종적으로는 Java 언어)에서 가치 유형을 더 잘 지원하는 근본적인 문제를 해결하기 위한 몇 가지 작업이 진행 중입니다.값 상태 문서를 참조하십시오.이는 예비적이고 추측적인 작업이며 JVM의 관점에서만 문제를 다루지만, 이미 상당한 검토가 이루어지고 있습니다.물론 이것이 Java 9에 들어가거나 어디에도 들어갈 수 있다는 보장은 없지만, 이 주제에 대한 현재의 사고방향을 보여줍니다.

다음 빌트인 클래스를 참조할 수 있습니다.

안타깝게도 자바8은 쌍이나 튜플을 도입하지 않았다.org.apache.commons.lang3은 언제든지 사용할 수 있습니다.물론 튜플(개인적으로는 Java 8과 조합하여 사용하고 있습니다) 또는 독자적인 래퍼를 작성할 수 있습니다.또는 지도를 사용합니다.또는 링크된 질문에 대한 답변에서 설명한 것과 같은 내용입니다.


업데이트: JDK 14에서는 레코드 클래스가 프리뷰 기능으로 도입되었으며, JDK 16에서는 표준 언어 기능으로 도입되었습니다.이것들은 튜플은 아니지만, 같은 문제를 해결하는 데 사용할 수 있습니다.위의 구체적인 예에서는 다음과 같습니다.

public class Jdk14Example {
    record CountForIndex(int index, long count) {}

    public static void main(String[] args) {
        boolean [][] directed_acyclic_graph = new boolean[][]{
                {false,  true, false,  true, false,  true},
                {false, false, false,  true, false,  true},
                {false, false, false,  true, false,  true},
                {false, false, false, false, false,  true},
                {false, false, false, false, false,  true},
                {false, false, false, false, false, false}
        };

        System.out.println(
                IntStream.range(0, directed_acyclic_graph.length)
                        .parallel()
                        .mapToObj(i -> {
                            long count = IntStream.range(0, directed_acyclic_graph[i].length)
                                            .filter(j -> directed_acyclic_graph[j][i])
                                            .count();
                            return new CountForIndex(i, count);
                        }
                        )
                        .filter(n -> n.count == 0)
                        .collect(() -> new ArrayList<CountForIndex>(), (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2))
        );
    }
}

컴파일하여 JDK 14에서 실행하는 경우--enable-previewflag 또는 JDK 16 이후에는 다음과 같은 결과가 나타납니다.

[CountForIndex[index=0, count=0], CountForIndex[index=2, count=0], CountForIndex[index=4, count=0]]

Java 9 이후로는 다음 인스턴스를 만들 수 있습니다.Map.Entry기존보다 간단:

Entry<Integer, String> pair = Map.entry(1, "a");

Map.entry 변경할 수 없는 것을 반환Entrynull을 금지합니다.

어떤 종류의 Pair 구조도 사용하지 않고 전체 예를 해결할 수 있을 것으로 보입니다.핵심은 열 인덱스를 열 인덱스의 수에 매핑하는 대신 술어가 열 전체를 체크하면서 열 인덱스를 필터링하는 것입니다.false엔트리가 표시됩니다.

이 작업을 수행하는 코드는 다음과 같습니다.

    System.out.println(
        IntStream.range(0, acyclic_graph.length)
            .filter(i -> IntStream.range(0, acyclic_graph.length)
                                  .noneMatch(j -> acyclic_graph[j][i]))
            .boxed()
            .collect(toList()));

그, 의, 의, 의, 의, 의, 의, 의, 니, this, this, this, this, this.[0, 2, 4]OP op op op op op op op op op op 。

이 때 해 주세요.boxed()「 」를 하는 int을 「」로 설정합니다.Integer이렇게 에 있던 것을 사용할 수 .toList()대신 콜렉터 기능을 직접 작성해야 합니다.

Vavr(이전의 Javaslang)(http://www.vavr.io에서는 8사이즈까지)도 제공하고 있습니다.javadoc: https://static.javadoc.io/io.vavr/vavr/0.9.0/io/vavr/Tuple.html 입니다.

다음은 간단한 예입니다.

Tuple2<Integer, String> entry = Tuple.of(1, "A");

Integer key = entry._1;
String value = entry._2;

왜 JDK 자체가 지금까지 단순한 종류의 튜플을 가지고 있지 않은지 의문입니다.랩퍼 수업을 쓰는 것은 일상적인 일인 것 같다.

네.

Map.Entry a a a a Pair.

유감스럽게도 Java 8 스트림에서는 도움이 되지 않습니다.문제는 lamda가 여러 인수를 사용할 수 있지만 Java 언어에서는 단일 값(개체 또는 원시 유형)만 반환할 수 있기 때문입니다.이는 스트림이 있을 때마다 이전 작업의 단일 개체가 전달된다는 것을 의미합니다.이는 Java 언어에서는 부족한 것입니다.복수 반환값이 지원되고 스트림도 이를 지원하면 스트림에서 훨씬 더 간단한 작업을 수행할 수 있기 때문입니다.

그때까지는 거의 쓸모가 없다.

EDIT 2021-05-10: Java 16은 이 문제 및 기타 문제에 대한 매우 훌륭한 해결책인 레코드를 제공했습니다.Java 17 LTS를 목표로 하는 매우 강력한 이유가 곧 발표됩니다.

인덱스에만 관심이 있으므로 튜플에 매핑할 필요가 없습니다.어레이 내에서 검색 요소를 사용하는 필터를 작성하면 어떨까요?

     int[] value =  ...


IntStream.range(0, value.length)
            .filter(i -> value[i] > 30)  //or whatever filter you want
            .forEach(i -> System.out.println(i));

에는 Eclipse가 있습니다.Pair및 원시/객체 쌍의 모든 조합(모든 8개의 원시 쌍에 해당)입니다.

공장에서는 다음 인스턴스를 생성할 수 있습니다.Pair공장에서는 프리미티브/오브젝트 쌍의 모든 조합을 작성할 수 있습니다.

Java 8이 출시되기 전에 추가했습니다.또한 모든 원시/객체 조합에서 지원하는 기본 맵의 키/값 반복을 구현하는 데 유용합니다.

오버헤드를 Stuart가를 원시적인 할 수 .IntList복싱을 피하려고요.Eclipse Collections 9.0에 새로운 메서드를 추가하여Int/Long/Double에서 Int/Long/Double★★★★★★★★★★★★★★★★★★.

IntList list = IntLists.mutable.withAll(intStream);

주의: 저는 Eclipse Collections의 커밋입니다.

많은 서드파티 라이브러리가 튜플을 지원합니다.예를 들어, jOO'는 도에서 튜플을 지원합니다.0로로 합니다.16 예: 개요:

// Assuming this static import
import static org.jooq.lambda.tuple.Tuple.*;

// Write:
var t = tuple(1, "a", 2L);
Integer i = t.v1;
String s = t.v2;
Long l = t.v3;

튜플이 있는 다른 라이브러리도 마찬가지입니다. 예:

언급URL : https://stackoverflow.com/questions/24328679/does-java-se-8-have-pairs-or-tuples

반응형