Функциональная коллекция Java и непроверенные предупреждения - PullRequest
0 голосов
/ 30 декабря 2018

Я написал чисто функциональный класс коллекции - bag aka multiset - и он отлично работает, но генерирует ряд предупреждений для непроверенного назначения, как в самом определении класса, так и при использовании, особенно при использовании FBag.make.Насколько я вижу, проблема возникает в первую очередь из-за того, что функциональные коллекции хотят использовать статические фабричные методы вместо открытых конструкторов, а статические методы не могут получить доступ к универсальному типу.

Существует ли элегантный способ избежать этого,или мне просто нужно прикусить пулю, признать, что это проблема стирания типа, и подавить предупреждения?

Код следует.(Я знаю, что эта реализация асимптотически неэффективна. Ожидается, что N будет небольшим; если это изменится, я изменю реализацию.)

import java.util.Collection;
import java.util.Iterator;

public class FBag<E> implements Iterable<E> {
    public static final FBag EMPTY = new FBag<>(null, null);
    private final FBag<E> next;
    private final E val;

    private FBag(E val, FBag<E> next) {
        this.val = val;
        this.next = next;
    }

    public FBag<E> add(E val) {
        return new FBag<>(val, this);
    }

    @Override
    public Iterator<E> iterator() {
        return new Iter<>(this);
    }

    public static FBag make(Collection c) {
        var p = EMPTY;
        for (var a : c) {
            p = p.add(a);
        }
        return p;
    }

    public static FBag make(Object[] c, int from, int to) {
        var p = EMPTY;
        for (var i = from; i < to; i++) {
            p = p.add(c[i]);
        }
        return p;
    }

    public FBag<E> remove(E val) {
        if (this == EMPTY) {
            return this;
        }
        if (this.val == val) {
            return next;
        }
        return new FBag<>(this.val, next.remove(val));
    }

    private static class Iter<E1> implements Iterator {
        private FBag<E1> p;

        Iter(FBag<E1> p) {
            this.p = p;
        }

        @Override
        public boolean hasNext() {
            return p != EMPTY;
        }

        @Override
        public Object next() {
            assert p != EMPTY;
            var r = p.val;
            p = p.next;
            return r;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Для static члена EMPTY, я считаю, что нет никакого способа обойти использование необработанного типа.То же самое можно увидеть в Collections.EMPTY_LIST:

@SuppressWarnings("rawtypes")
public static final List EMPTY_LIST = new EmptyList<>();

@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

Поэтому все, что вы можете здесь сделать, это подавить предупреждение:

@SuppressWarnings("rawtypes")
public static final FBag EMPTY = new FBag<>(null, null);

@SuppressWarnings("unchecked")
public static final <T> FBag<T> empty() {
    return (FBag<T>) EMPTY;
}

С другой стороны, для staticметоды, которыми вы можете объявить свои собственные переменные универсального типа.

public static <E> FBag<E> make(Collection<E> c) {
    FBag<E> p = empty ();
    for (E a : c) {
        p = p.add(a);
    }
    return p;
}

public static <E> FBag<E> make(E[] c, int from, int to) {
    FBag<E> p = empty ();
    for (int i = from; i < to; i++) {
        p = p.add(c[i]);
    }
    return p;
}

(я заменил var с явными объявлениями, так как у меня не установлена ​​Java 10, и я не хотел публиковать без проверкикод).

0 голосов
/ 30 декабря 2018

static метод может иметь свои собственные общие объявления, которые вы можете использовать для создания Fbag<T> из Collection<T> или T[]:

public static <T> FBag<T> make(Collection<? extends T> c) {
    var p = EMPTY;
    for (var a : c) {
        p = p.add(a);
    }
    return p;
}

public static <T> FBag<T> make(T[] c, int from, int to) {
    var p = EMPTY;
    for (var i = from; i < to; i++) {
        p = p.add(c[i]);
    }
    return p;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...