[java] Java에서 순차 정수 목록 또는 배열을 생성하려면 어떻게해야합니까?

를 생성하는 짧고 달콤한 방법이 있나요 List<Integer>, 또는 아마도 Integer[]또는 int[]일부에서 순차 값, start가치 end가치인가?

즉, 다음보다 짧지 만 1에 해당합니다.

void List<Integer> makeSequence(int begin, int end) {
  List<Integer> ret = new ArrayList<>(end - begin + 1);
  for (int i=begin; i<=end; i++) {
    ret.add(i);
  }
  return ret;
}

구아바 사용은 괜찮습니다.

최신 정보:

성능 분석

이 질문은 네이티브 Java 8 및 타사 라이브러리를 사용하여 몇 가지 좋은 답변을 받았으므로 모든 솔루션의 성능을 테스트 할 것이라고 생각했습니다.

첫 번째 테스트 [1..10]는 다음 방법을 사용하여 10 개의 요소 목록을 만드는 것을 테스트 합니다.

  • classicArrayList : 내 질문에서 위에 주어진 코드 (그리고 본질적으로 adarshr의 대답과 동일).
  • eclipseCollections : Eclipse Collections 8.0을 사용하여 아래 Donald의 답변에 제공된 코드 .
  • guavaRange : 아래 daveb 의 답변에 제공된 코드 . 기술적으로 이것은 a를 생성하는 List<Integer>것이 아니라 순서대로 ContiguousSet<Integer>구현 Iterable<Integer>하기 때문에 대부분 내 목적에 적합합니다.
  • intStreamRange : 아래 Vladimir의 답변에 제공된 코드 IntStream.rangeClosed()로 Java 8에서 도입 된-를 사용합니다 .
  • streamIterate : Java 8에 도입 된 기능 을 사용하는 아래 Catalin의 답변에 제공된 코드 IntStream입니다.

다음은 목록 크기가 10 인 위의 모든 항목에 대한 초당 킬로 작업 (숫자가 클수록 좋음)의 결과입니다.

목록 생성 처리량

… 그리고 다시 한번 크기가 10,000 인 목록 :

여기에 이미지 설명 입력

마지막 차트는 정확합니다. Eclipse 및 Guava 이외의 솔루션은 너무 느려 단일 픽셀 막대를 얻을 수도 없습니다! 빠른 솔루션은 나머지 솔루션보다 10,000 ~ 20,000 빠릅니다.

물론 여기서 진행되는 것은 구아바와 이클립스 솔루션이 실제로 10,000 개의 요소 목록을 구체화하지 않는다는 것입니다. 단순히 시작과 끝점을 둘러싼 고정 된 크기의 래퍼입니다. 각 요소는 반복 중에 필요에 따라 생성됩니다. 이 테스트에서는 실제로 반복하지 않기 때문에 비용이 지연됩니다. 다른 모든 솔루션은 실제로 전체 목록을 메모리에 구체화하고 생성 전용 벤치 마크에서 많은 비용을 지불합니다.

좀 더 현실적인 작업을하고 모든 정수를 반복하여 합산 해 봅시다. 따라서 IntStream.rangeClosed변형 의 경우 벤치 마크는 다음과 같습니다.

@Benchmark
public int intStreamRange() {
    List<Integer> ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());

    int total = 0;
    for (int i : ret) {
        total += i;
    }
    return total;
}

여기서 비 물질화 솔루션이 여전히 가장 빠르지 만 그림은 많이 변경됩니다. 길이 = 10입니다.

List <Integer> 반복 (길이 = 10)

… 및 길이 = 10,000 :

List <Integer> 반복 (길이 = 10,000)

많은 요소에 대한 긴 반복은 많은 것을 고르게하지만 일식과 구아바는 10,000 개의 요소 테스트에서도 두 배 이상 빠르게 유지됩니다.

따라서 정말로List<Integer> , eclipse 컬렉션을 원한다면 이클립스 컬렉션이 최선의 선택 인 것처럼 보이지만 물론 더 네이티브 방식으로 스트림을 사용한다면 (예 : .boxed()원시 도메인을 잊어 버리고 축소하는 것) 아마이 모든 것보다 더 빨리 끝날 것입니다. 변형.


1 오류 처리 (예 : end< begin인 경우) 또는 크기가 일부 구현 또는 JVM 제한을 초과하는 경우 (예 : 2^31-1.



답변

Java 8을 사용하면 매우 간단하므로 더 이상 별도의 메서드가 필요하지 않습니다.

List<Integer> range = IntStream.rangeClosed(start, end)
    .boxed().collect(Collectors.toList());


답변

글쎄,이 라이너는 자격이 될 수 있습니다 ( 구아바 범위 사용 )

ContiguousSet<Integer> integerList = ContiguousSet.create(Range.closedOpen(0, 10), DiscreteDomain.integers());
System.out.println(integerList);

이것은을 만들지 않습니다 List<Integer>,하지만 ContiguousSet구현 특히, 거의 같은 기능을 제공 Iterable<Integer>할 수있는 foreach같은 방법으로 구현 List<Integer>.

구아바 14 이전 버전에서는 다음을 사용할 수 있습니다.

ImmutableList<Integer> integerList = Ranges.closedOpen(0, 10).asSet(DiscreteDomains.integers()).asList();
System.out.println(integerList);

둘 다 생산 :

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


답변

다음 한 줄짜리 Java 8 버전은 [1, 2, 3 … 10]을 생성합니다. 의 첫 번째 인수 iterate는 시퀀스의 첫 번째 nr이고 첫 번째 인수 limit는 마지막 숫자입니다.

List<Integer> numbers = Stream.iterate(1, n -> n + 1)
                              .limit(10)
                              .collect(Collectors.toList());


답변

Eclipse CollectionsInterval클래스를 사용할 수 있습니다 .

List<Integer> range = Interval.oneTo(10);
range.forEach(System.out::print);  // prints 12345678910

Interval클래스는 게으른, 그래서 모든 값을 저장하지 않습니다.

LazyIterable<Integer> range = Interval.oneTo(10);
System.out.println(range.makeString(",")); // prints 1,2,3,4,5,6,7,8,9,10

귀하의 방법은 다음과 같이 구현할 수 있습니다.

public List<Integer> makeSequence(int begin, int end) {
    return Interval.fromTo(begin, end);
}

int를 Integers로 사용하는 것을 피하고 싶지만 결과적으로 목록 구조를 원하는 경우 Eclipse Collections에서 IntListwith IntInterval를 사용할 수 있습니다 .

public IntList makeSequence(int begin, int end) {
    return IntInterval.fromTo(begin, end);
}

IntList이 방법 sum(), min(), minIfEmpty(), max(), maxIfEmpty(), average()median()인터페이스에 사용할 수 있습니다.

명확성을위한 업데이트 : 2017 년 11 월 27 일

An IntervalList<Integer>이지만 게으르고 변경할 수 없습니다. 특히 컬렉션을 많이 다루는 경우 테스트 데이터를 생성하는 데 매우 유용합니다. 당신이 원하는 경우에 당신은에 간격을 복사 쉽게 할 수 있습니다 List, Set또는 Bag같은 다음과 같습니다 :

Interval integers = Interval.oneTo(10);
Set<Integer> set = integers.toSet();
List<Integer> list = integers.toList();
Bag<Integer> bag = integers.toBag();

IntInterval이다 ImmutableIntList연장 IntList. 또한 변환기 방법이 있습니다.

IntInterval ints = IntInterval.oneTo(10);
IntSet set = ints.toSet();
IntList list = ints.toList();
IntBag bag = ints.toBag();

An Interval과 an IntInterval은 동일한 equals계약을 가지고 있지 않습니다 .

Eclipse Collections 9.0 업데이트

이제 기본 스트림에서 기본 컬렉션을 만들 수 있습니다. 있다 withAllofAll환경 설정에 따라 방법. 궁금한 점이 있으면 여기에 둘 다있는 이유를 설명 합니다 . 이러한 메소드는 변경 가능하고 변경 불가능한 Int / Long / Double 목록, 세트, ​​백 및 스택에 존재합니다.

Assert.assertEquals(
        IntInterval.oneTo(10),
        IntLists.mutable.withAll(IntStream.rangeClosed(1, 10)));

Assert.assertEquals(
        IntInterval.oneTo(10),
        IntLists.immutable.withAll(IntStream.rangeClosed(1, 10)));

참고 : 저는 Eclipse 컬렉션 커미터입니다.


답변

이것은 Core Java를 사용할 수있는 가장 짧은 것입니다.

List<Integer> makeSequence(int begin, int end) {
  List<Integer> ret = new ArrayList(end - begin + 1);

  for(int i = begin; i <= end; i++, ret.add(i));

  return ret;
}


답변

Guava Ranges를 사용할 수 있습니다.

다음 SortedSet을 사용하여 얻을 수 있습니다.

ImmutableSortedSet<Integer> set = Ranges.open(1, 5).asSet(DiscreteDomains.integers());
// set contains [2, 3, 4]


답변

이것은 내가 찾을 수있는 가장 짧은 것입니다.

목록 버전

public List<Integer> makeSequence(int begin, int end)
{
    List<Integer> ret = new ArrayList<Integer>(++end - begin);

    for (; begin < end; )
        ret.add(begin++);

    return ret;
}

어레이 버전

public int[] makeSequence(int begin, int end)
{
    if(end < begin)
        return null;

    int[] ret = new int[++end - begin];
    for (int i=0; begin < end; )
        ret[i++] = begin++;
    return ret;
}