복붙노트

[SCALA] 자바 8 스트림 API와 정수의 목록을 셔플

SCALA

자바 8 스트림 API와 정수의 목록을 셔플

나는 스트림 API를 사용하여 Java 8 스칼라의 다음 줄을 번역하려고 :

// Scala
util.Random.shuffle((1 to 24).toList)

내가 정수의 범위를 만든 자바에서 동등한를 작성하려면 :

IntStream.range(1, 25)

나는 스트림 API에 toList 방법을 찾기 위해 의심하지만, IntStream 만 이상한 방법을 알고있다 :

collect(
  Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)

어떻게 자바 8 스트림 API를 사용하여 목록을 셔플 할 수 있습니까?

해결법

  1. ==============================

    1.여기 가서 :

    여기 가서 :

    List<Integer> integers =
        IntStream.range(1, 10)                      // <-- creates a stream of ints
            .boxed()                                // <-- converts them to Integers
            .collect(Collectors.toList());          // <-- collects the values to a list
    
    Collections.shuffle(integers);
    
    System.out.println(integers);
    

    인쇄물:

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

    2.다음 toShuffledList () 메소드가 유용 할 수있다.

    다음 toShuffledList () 메소드가 유용 할 수있다.

    private static final Collector<?, ?, ?> SHUFFLER = Collectors.collectingAndThen(
            Collectors.toCollection(ArrayList::new),
            list -> {
                Collections.shuffle(list);
                return list;
            }
    );
    
    @SuppressWarnings("unchecked")
    public static <T> Collector<T, ?, List<T>> toShuffledList() {
        return (Collector<T, ?, List<T>>) SHUFFLER;
    }
    

    이 한 줄의 다음과 같은 종류의 수 있습니다 :

    IntStream.rangeClosed('A', 'Z')
             .mapToObj(a -> (char) a)
             .collect(toShuffledList())
             .forEach(System.out::print);
    

    출력 예 :

    AVBFYXIMUDENOTHCRJKWGQZSPL
    
  3. ==============================

    3.당신은 사용자 정의 비교기를 사용할 수있는 "종류"임의의 값으로 값 :

    당신은 사용자 정의 비교기를 사용할 수있는 "종류"임의의 값으로 값 :

    public final class RandomComparator<T> implements Comparator<T> {
    
        private final Map<T, Integer> map = new IdentityHashMap<>();
        private final Random random;
    
        public RandomComparator() {
            this(new Random());
        }
    
        public RandomComparator(Random random) {
            this.random = random;
        }
    
        @Override
        public int compare(T t1, T t2) {
            return Integer.compare(valueFor(t1), valueFor(t2));
        }
    
        private int valueFor(T t) {
            synchronized (map) {
                return map.computeIfAbsent(t, ignore -> random.nextInt());
            }
        }
    
    }
    

    스트림의 각 개체는에 우리 일종의 임의의 정수 값을, 연관 (느리게)입니다. 지도에 동기화는 병렬 스트림을 처리하는 것입니다.

    그런 다음처럼 사용할 수 있습니다 :

    IntStream.rangeClosed(0, 24).boxed()
        .sorted(new RandomComparator<>())
        .collect(Collectors.toList());
    

    이 솔루션의 장점은 스트림 파이프 라인 내에서 통합되어 있다는 것입니다.

  4. ==============================

    4.셔플을 수행하려면 효율적으로 사전에 모든 값이 필요합니다. 당신이 스칼라처럼 당신이 목록에 스트림을 변환 한 후에는 Collections.shuffle ()를 사용할 수 있습니다.

    셔플을 수행하려면 효율적으로 사전에 모든 값이 필요합니다. 당신이 스칼라처럼 당신이 목록에 스트림을 변환 한 후에는 Collections.shuffle ()를 사용할 수 있습니다.

  5. ==============================

    5.당신은 너무 많은 번거 로움없이 전체 스트림을 처리하려면, 당신은 단순히 Collectors.collectingAndThen ()를 사용하여 자신의 수집기를 만들 수 있습니다 :

    당신은 너무 많은 번거 로움없이 전체 스트림을 처리하려면, 당신은 단순히 Collectors.collectingAndThen ()를 사용하여 자신의 수집기를 만들 수 있습니다 :

    public static <T> Collector<T, ?, Stream<T>> toEagerShuffledStream() {
        return Collectors.collectingAndThen(
          toList(),
          list -> {
              Collections.shuffle(list);
              return list.stream();
          });
    }
    

    당신은 (제한하려면하지만이) 잘 결과 스트림을 수행하지 않습니다. 이 문제를 극복하기 위해, 하나는 사용자 정의 Spliterator를 만들 수 있습니다 :

    package com.pivovarit.stream;
    
    import java.util.List;
    import java.util.Random;
    import java.util.Spliterator;
    import java.util.function.Consumer;
    import java.util.function.Supplier;
    
    public class ImprovedRandomSpliterator<T> implements Spliterator<T> {
    
        private final Random random;
        private final T[] source;
        private int size;
    
        ImprovedRandomSpliterator(List<T> source, Supplier<? extends Random> random) {
            if (source.isEmpty()) {
                throw new IllegalArgumentException("RandomSpliterator can't be initialized with an empty collection");
            }
            this.source = (T[]) source.toArray();
            this.random = random.get();
            this.size = this.source.length;
        }
    
        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            int nextIdx = random.nextInt(size);
            int lastIdx = size - 1;
    
            action.accept(source[nextIdx]);
            source[nextIdx] = source[lastIdx];
            source[lastIdx] = null; // let object be GCed
            return --size > 0;
        }
    
        @Override
        public Spliterator<T> trySplit() {
            return null;
        }
    
        @Override
        public long estimateSize() {
            return source.length;
        }
    
        @Override
        public int characteristics() {
            return SIZED;
        }
    }
    

    그리고:

    public final class RandomCollectors {
    
        private RandomCollectors() {
        }
    
        public static <T> Collector<T, ?, Stream<T>> toImprovedLazyShuffledStream() {
            return Collectors.collectingAndThen(
              toCollection(ArrayList::new),
              list -> !list.isEmpty()
                ? StreamSupport.stream(new ImprovedRandomSpliterator<>(list, Random::new), false)
                : Stream.empty());
        }
    
        public static <T> Collector<T, ?, Stream<T>> toEagerShuffledStream() {
            return Collectors.collectingAndThen(
              toCollection(ArrayList::new),
              list -> {
                  Collections.shuffle(list);
                  return list.stream();
              });
        }
    }
    

    내가 여기에 성능 고려 사항을 설명했다 https://4comprehension.com/implementing-a-randomized-stream-spliterator-in-java/

  6. ==============================

    6.당신이 찾고있는 경우 "임의의"주문 대 용액과 결정, 단순히 "우연"주문 "만 스트리밍"충분히 좋은이며, 할 수 있습니다 항상 일종의 해시 값만큼의 int :

    당신이 찾고있는 경우 "임의의"주문 대 용액과 결정, 단순히 "우연"주문 "만 스트리밍"충분히 좋은이며, 할 수 있습니다 항상 일종의 해시 값만큼의 int :

    List<Integer> xs=IntStream.range(0, 10)
        .boxed()
        .sorted( (a, b) -> a.hashCode() - b.hashCode() )
        .collect(Collectors.toList());
    

    당신이 오히려 목록 <정수>보다 지능 []이 원하는 경우, 당신은 나중에 그들을 언 박싱 수 있습니다. 불행하게도, 당신은 그래서 과정의 일부가 제거있어, 사용자 지정 비교기를 적용 할 권투 단계를 통과 없었다.

    List<Integer> ys=IntStream.range(0, 10)
        .boxed()
        .sorted( (a, b) -> a.hashCode() - b.hashCode() )
        .mapToInt( a -> a.intValue())
        .toArray();
    
  7. ==============================

    7.

    public static List<Integer> getSortedInRandomOrder(List<Integer> list) {
        return list
                .stream()
                .sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(-1, 2))
                .collect(Collectors.toList());
    }
    
  8. ==============================

    8.이것은 내 하나의 라인 솔루션입니다 : 나는 1 개 임의의 색상을 따기입니다 :

    이것은 내 하나의 라인 솔루션입니다 : 나는 1 개 임의의 색상을 따기입니다 :

    colourRepository.findAll().stream().sorted((o1,o2)-> RandomUtils.nextInt(-1,1)).findFirst().get()
    
  9. from https://stackoverflow.com/questions/20058366/shuffle-a-list-of-integers-with-java-8-streams-api by cc-by-sa and MIT license