WeightedList.java

net.minecraft.util.random.WeightedList

信息

  • 全限定名:net.minecraft.util.random.WeightedList
  • 类型:public final class
  • 包:net.minecraft.util.random
  • 源码路径:src/main/java/net/minecraft/util/random/WeightedList.java
  • 起始行号:L19
  • 职责:

    TODO

字段/常量

  • FLAT_THRESHOLD

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L20
    • 说明:

      TODO

  • totalWeight

    • 类型: int
    • 修饰符: private final
    • 源码定位: L21
    • 说明:

      TODO

  • items

    • 类型: List<Weighted<E>>
    • 修饰符: private final
    • 源码定位: L22
    • 说明:

      TODO

  • selector

    • 类型: WeightedList.Selector<E>
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.util.random.WeightedList.Builder

    • 类型: class
    • 修饰符: public static
    • 源码定位: L146
    • 说明:

      TODO

  • net.minecraft.util.random.WeightedList.Compact

    • 类型: class
    • 修饰符: private static
    • 源码定位: L163
    • 说明:

      TODO

  • net.minecraft.util.random.WeightedList.Flat

    • 类型: class
    • 修饰符: private static
    • 源码定位: L183
    • 说明:

      TODO

  • net.minecraft.util.random.WeightedList.Selector

    • 类型: interface
    • 修饰符: private
    • 源码定位: L203
    • 说明:

      TODO

构造器

private WeightedList(List<?extends Weighted<E>> items) @ L25

  • 构造器名:WeightedList
  • 源码定位:L25
  • 修饰符:private

参数:

  • items: List<?extends Weighted>

说明:

TODO

方法

下面的方法块按源码顺序生成。

public static <E> WeightedList<E> of() @ L37

  • 方法名:of
  • 源码定位:L37
  • 返回类型: WeightedList
  • 修饰符:public static

参数:

说明:

TODO

public static <E> WeightedList<E> of(E value) @ L41

  • 方法名:of
  • 源码定位:L41
  • 返回类型: WeightedList
  • 修饰符:public static

参数:

  • value: E

说明:

TODO

public static <E> WeightedList<E> of(Weighted<E>... items) @ L45

  • 方法名:of
  • 源码定位:L45
  • 返回类型: WeightedList
  • 修饰符:public static

参数:

  • items: Weighted

说明:

TODO

public static <E> WeightedList<E> of(List<Weighted<E>> items) @ L50

  • 方法名:of
  • 源码定位:L50
  • 返回类型: WeightedList
  • 修饰符:public static

参数:

  • items: List<Weighted>

说明:

TODO

public static <E> WeightedList.Builder<E> builder() @ L54

  • 方法名:builder
  • 源码定位:L54
  • 返回类型: WeightedList.Builder
  • 修饰符:public static

参数:

说明:

TODO

public boolean isEmpty() @ L58

  • 方法名:isEmpty
  • 源码定位:L58
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public <T> WeightedList<T> map(Function<E,T> mapper) @ L62

  • 方法名:map
  • 源码定位:L62
  • 返回类型: WeightedList
  • 修饰符:public

参数:

  • mapper: Function<E,T>

说明:

TODO

public Optional<E> getRandom(RandomSource random) @ L66

  • 方法名:getRandom
  • 源码定位:L66
  • 返回类型:Optional
  • 修饰符:public

参数:

  • random: RandomSource

说明:

TODO

public E getRandomOrThrow(RandomSource random) @ L75

  • 方法名:getRandomOrThrow
  • 源码定位:L75
  • 返回类型:E
  • 修饰符:public

参数:

  • random: RandomSource

说明:

TODO

public List<Weighted<E>> unwrap() @ L84

  • 方法名:unwrap
  • 源码定位:L84
  • 返回类型:List<Weighted>
  • 修饰符:public

参数:

说明:

TODO

private static <E> Codec<WeightedList<E>> entryToListCodec(Codec<Weighted<E>> weightedElementCodec) @ L88

  • 方法名:entryToListCodec
  • 源码定位:L88
  • 返回类型: Codec<WeightedList>
  • 修饰符:private static

参数:

  • weightedElementCodec: Codec<Weighted>

说明:

TODO

public static <E> Codec<WeightedList<E>> codec(Codec<E> elementCodec) @ L92

  • 方法名:codec
  • 源码定位:L92
  • 返回类型: Codec<WeightedList>
  • 修饰符:public static

参数:

  • elementCodec: Codec

说明:

TODO

public static <E> Codec<WeightedList<E>> codec(MapCodec<E> elementCodec) @ L96

  • 方法名:codec
  • 源码定位:L96
  • 返回类型: Codec<WeightedList>
  • 修饰符:public static

参数:

  • elementCodec: MapCodec

说明:

TODO

private static <E> Codec<WeightedList<E>> entryToNonEmptyListCodec(Codec<Weighted<E>> weightedElementCodec) @ L100

  • 方法名:entryToNonEmptyListCodec
  • 源码定位:L100
  • 返回类型: Codec<WeightedList>
  • 修饰符:private static

参数:

  • weightedElementCodec: Codec<Weighted>

说明:

TODO

public static <E> Codec<WeightedList<E>> nonEmptyCodec(Codec<E> elementCodec) @ L109

  • 方法名:nonEmptyCodec
  • 源码定位:L109
  • 返回类型: Codec<WeightedList>
  • 修饰符:public static

参数:

  • elementCodec: Codec

说明:

TODO

public static <E> Codec<WeightedList<E>> nonEmptyCodec(MapCodec<E> elementCodec) @ L113

  • 方法名:nonEmptyCodec
  • 源码定位:L113
  • 返回类型: Codec<WeightedList>
  • 修饰符:public static

参数:

  • elementCodec: MapCodec

说明:

TODO

public static <E,B extends ByteBuf> StreamCodec<B,WeightedList<E>> streamCodec(StreamCodec<B,E> elementCodec) @ L117

  • 方法名:streamCodec
  • 源码定位:L117
  • 返回类型:<E,B extends ByteBuf> StreamCodec<B,WeightedList>
  • 修饰符:public static

参数:

  • elementCodec: StreamCodec<B,E>

说明:

TODO

public boolean contains(E value) @ L121

  • 方法名:contains
  • 源码定位:L121
  • 返回类型:boolean
  • 修饰符:public

参数:

  • value: E

说明:

TODO

public boolean equals(Object obj) @ L131

  • 方法名:equals
  • 源码定位:L131
  • 返回类型:boolean
  • 修饰符:public

参数:

  • obj: Object

说明:

TODO

public int hashCode() @ L140

  • 方法名:hashCode
  • 源码定位:L140
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

代码

public final class WeightedList<E> {
    private static final int FLAT_THRESHOLD = 64;
    private final int totalWeight;
    private final List<Weighted<E>> items;
    private final WeightedList.@Nullable Selector<E> selector;
 
    private WeightedList(List<? extends Weighted<E>> items) {
        this.items = List.copyOf(items);
        this.totalWeight = WeightedRandom.getTotalWeight(items, Weighted::weight);
        if (this.totalWeight == 0) {
            this.selector = null;
        } else if (this.totalWeight < 64) {
            this.selector = new WeightedList.Flat<>(this.items, this.totalWeight);
        } else {
            this.selector = new WeightedList.Compact<>(this.items);
        }
    }
 
    public static <E> WeightedList<E> of() {
        return new WeightedList<>(List.of());
    }
 
    public static <E> WeightedList<E> of(E value) {
        return new WeightedList<>(List.of(new Weighted<>(value, 1)));
    }
 
    @SafeVarargs
    public static <E> WeightedList<E> of(Weighted<E>... items) {
        return new WeightedList<>(List.of(items));
    }
 
    public static <E> WeightedList<E> of(List<Weighted<E>> items) {
        return new WeightedList<>(items);
    }
 
    public static <E> WeightedList.Builder<E> builder() {
        return new WeightedList.Builder<>();
    }
 
    public boolean isEmpty() {
        return this.selector == null;
    }
 
    public <T> WeightedList<T> map(Function<E, T> mapper) {
        return new WeightedList(Lists.transform(this.items, e -> e.map((Function<E, E>)mapper)));
    }
 
    public Optional<E> getRandom(RandomSource random) {
        if (this.selector == null) {
            return Optional.empty();
        } else {
            int selection = random.nextInt(this.totalWeight);
            return Optional.of(this.selector.get(selection));
        }
    }
 
    public E getRandomOrThrow(RandomSource random) {
        if (this.selector == null) {
            throw new IllegalStateException("Weighted list has no elements");
        } else {
            int selection = random.nextInt(this.totalWeight);
            return this.selector.get(selection);
        }
    }
 
    public List<Weighted<E>> unwrap() {
        return this.items;
    }
 
    private static <E> Codec<WeightedList<E>> entryToListCodec(Codec<Weighted<E>> weightedElementCodec) {
        return weightedElementCodec.listOf().xmap(WeightedList::of, WeightedList::unwrap);
    }
 
    public static <E> Codec<WeightedList<E>> codec(Codec<E> elementCodec) {
        return entryToListCodec(Weighted.codec(elementCodec));
    }
 
    public static <E> Codec<WeightedList<E>> codec(MapCodec<E> elementCodec) {
        return entryToListCodec(Weighted.codec(elementCodec));
    }
 
    private static <E> Codec<WeightedList<E>> entryToNonEmptyListCodec(Codec<Weighted<E>> weightedElementCodec) {
        return entryToListCodec(weightedElementCodec)
            .validate(
                list -> list.isEmpty()
                    ? DataResult.error(() -> "Weighted list must contain at least one entry with non-zero weight")
                    : DataResult.success(list)
            );
    }
 
    public static <E> Codec<WeightedList<E>> nonEmptyCodec(Codec<E> elementCodec) {
        return entryToNonEmptyListCodec(Weighted.codec(elementCodec));
    }
 
    public static <E> Codec<WeightedList<E>> nonEmptyCodec(MapCodec<E> elementCodec) {
        return entryToNonEmptyListCodec(Weighted.codec(elementCodec));
    }
 
    public static <E, B extends ByteBuf> StreamCodec<B, WeightedList<E>> streamCodec(StreamCodec<B, E> elementCodec) {
        return Weighted.streamCodec(elementCodec).apply(ByteBufCodecs.list()).map(WeightedList::of, WeightedList::unwrap);
    }
 
    public boolean contains(E value) {
        for (Weighted<E> item : this.items) {
            if (item.value().equals(value)) {
                return true;
            }
        }
 
        return false;
    }
 
    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) {
            return true;
        } else {
            return !(obj instanceof WeightedList<?> list) ? false : this.totalWeight == list.totalWeight && Objects.equals(this.items, list.items);
        }
    }
 
    @Override
    public int hashCode() {
        int result = this.totalWeight;
        return 31 * result + this.items.hashCode();
    }
 
    public static class Builder<E> {
        private final ImmutableList.Builder<Weighted<E>> result = ImmutableList.builder();
 
        public WeightedList.Builder<E> add(E item) {
            return this.add(item, 1);
        }
 
        public WeightedList.Builder<E> add(E item, int weight) {
            this.result.add(new Weighted<>(item, weight));
            return this;
        }
 
        public WeightedList<E> build() {
            return new WeightedList<>(this.result.build());
        }
    }
 
    private static class Compact<E> implements WeightedList.Selector<E> {
        private final Weighted<?>[] entries;
 
        private Compact(List<Weighted<E>> entries) {
            this.entries = entries.toArray(Weighted[]::new);
        }
 
        @Override
        public E get(int selection) {
            for (Weighted<?> entry : this.entries) {
                selection -= entry.weight();
                if (selection < 0) {
                    return (E)entry.value();
                }
            }
 
            throw new IllegalStateException(selection + " exceeded total weight");
        }
    }
 
    private static class Flat<E> implements WeightedList.Selector<E> {
        private final Object[] entries;
 
        private Flat(List<Weighted<E>> entries, int totalWeight) {
            this.entries = new Object[totalWeight];
            int i = 0;
 
            for (Weighted<E> entry : entries) {
                int weight = entry.weight();
                Arrays.fill(this.entries, i, i + weight, entry.value());
                i += weight;
            }
        }
 
        @Override
        public E get(int selection) {
            return (E)this.entries[selection];
        }
    }
 
    private interface Selector<E> {
        E get(int selection);
    }
}

引用的其他类

  • ByteBufCodecs

    • 引用位置: 方法调用
    • 关联成员: ByteBufCodecs.list()
  • StreamCodec

    • 引用位置: 参数/返回值
  • RandomSource

    • 引用位置: 参数
  • Weighted

    • 引用位置: 参数/字段/方法调用/返回值
    • 关联成员: Weighted.codec(), Weighted.streamCodec()
  • WeightedRandom

    • 引用位置: 方法调用
    • 关联成员: WeightedRandom.getTotalWeight()