Cons'ing список в Java

Удалось заставить его работать, если это кому-нибудь поможет:

 string request_code = "";

            if (dict.TryGetValue("data", out data))
            {
                int dataLength = ((List<object>)data).Count;
                for (int i = 0; i < dataLength; i++)
                {
                    var rc = ((List<object>)data)[i];
                    var rc2 = (((Dictionary<string, object>)rc)["id"]);
                    request_code = (string)rc2;
                    Debug.Log("request_code=" + request_code);
                }
            }
5
задан Kevin Bourrillion 5 January 2010 в 18:37
поделиться

9 ответов

public static<T> List<T> cons(List<T> list, T t) {
    ArrayList<T> result = new ArrayList<T>(list);
    result.add(0, t);
    return result;
}

Отредактировано в ответ на комментарии: Поскольку вопрос задавался о «самом простом и / или наиболее эффективном способе реализации минусов», я выбрал «самый простой». Я не удивлюсь, узнав, что есть более эффективные способы. Размещение элемента перед списком - это еще один правильный подход, и первоначальное выделение правильного размера может, вероятно, повысить производительность. Преждевременная оптимизация - корень всего зла.

8
ответ дан 18 December 2019 в 05:29
поделиться

Clojure предоставляет подобные вещи из Lisp-y. В то время как большинство людей думают об использовании Clojure для языка (как и я), все библиотеки Clojure представляют собой настоящий код Java, и вы можете использовать структуры данных из Java как просто специальную библиотеку, если хотите. Таким образом, вы получите способность делать минусы и тому подобное, и вы получите неизменность, которую использует Clojure. Строковые данные Clojure также реализуют эквивалентные типы Java.

Просто мысль из другого направления.

7
ответ дан 18 December 2019 в 05:29
поделиться

Не могли бы вы использовать CompositeCollection ?

public Collection cons(Collection c1, Collection c2)
{
    CompositeCollection cons = new CompositeCollection();
    cons.addComposited(c1);
    cons.addComposited(c2);
    return cons;
}

Это не будет зависеть от того, является ли один из параметров неизменным и поддерживается ли исходная коллекция c1 и c2.

Если вам нужен список , я бы, вероятно, сделал следующее:

public List cons(Collection c1, Collection c2)
{
    ArrayList cons = new ArrayList(c1.size() + c2.size());
    cons.addAll(c1);
    cons.addAll(c2);
    return cons;
}
2
ответ дан 18 December 2019 в 05:29
поделиться

Поскольку вы упоминаете функцию cons , я предполагаю, что вы подходите к этой проблеме с концептуальной моделью связанных списков, состоящих из ячеек cons , В частности, я предполагаю, что вы думаете о каждом списке, имеющем car (первый элемент) и cdr (подсписок, содержащий все следующие элементы).

Java поддерживает связанный перечисляет как java.util.LinkedList . Они хороши для линейного обхода и могут очень эффективно вставлять элементы. Они наиболее похожи на связанные списки, о которых я упоминал выше.

Java также предлагает java.util.ArrayList . Списки такого типа хороши для произвольного доступа, но могут быть медленными при вставке элементов. По факту, они медленнее всего при вставке элемента в начале списка. Поскольку ArrayList реализованы как массивы за сценой, каждый элемент должен быть скопирован на одну позицию вперед в списке, чтобы освободить место для нового первого элемента. Теперь, если вам также понадобится массив большего размера, ArrayList выделит новый массив, скопирует все элементы и т. Д.

(цитируется Google ImmutableList как «произвольный доступ», поэтому он, скорее всего, больше похож на последний.)

Если вы планируете часто использовать метод cons , я рекомендую использовать его со связанными списками. Операция cons по существу добавляет элемент в начало списка. Это имеет мало смысла для линейных структур, таких как массивы. Я рекомендую не использовать списки массивов по этой причине: что они концептуально не подходят для работы.

Для очень требовательного: поскольку новый список возвращается каждый раз, когда вызывается cons , копирование должно происходить независимо от того, является ли список LinkedList или ArrayList . Однако весь принцип операции cons заключается в том, что она работает со связанным списком.

public <E> LinkedList<E> cons(E car, List<E> cdr) {
    LinkedList<E> destination = new LinkedList<E>(cdr);
    destination.addFirst(car);
    return destination;
}

Обратите внимание, что приведенный выше код был написан после прочтения вышеупомянутых ответов, поэтому я прошу прощения за любой случайный плагиат. Дайте мне знать, если вы увидите это, и я правильно подтвердю.

Предполагая, что вы счастливы вернуть LinkedList , вы можете использовать ImmutableList в качестве cdr в этом примере.

поскольку новый список возвращается каждый раз, когда вызывается cons , копирование должно происходить независимо от того, является ли список LinkedList или ArrayList . Однако весь принцип операции cons заключается в том, что она работает со связанным списком.

public <E> LinkedList<E> cons(E car, List<E> cdr) {
    LinkedList<E> destination = new LinkedList<E>(cdr);
    destination.addFirst(car);
    return destination;
}

Обратите внимание, что приведенный выше код был написан после прочтения вышеупомянутых ответов, поэтому я прошу прощения за любой случайный плагиат. Дайте мне знать, если вы увидите это, и я правильно подтвердю.

Предполагая, что вы счастливы вернуть LinkedList , вы можете использовать ImmutableList в качестве cdr в этом примере.

поскольку новый список возвращается каждый раз, когда вызывается cons , копирование должно происходить независимо от того, является ли список LinkedList или ArrayList . Однако весь принцип операции cons заключается в том, что она работает со связанным списком.

public <E> LinkedList<E> cons(E car, List<E> cdr) {
    LinkedList<E> destination = new LinkedList<E>(cdr);
    destination.addFirst(car);
    return destination;
}

Обратите внимание, что приведенный выше код был написан после прочтения вышеупомянутых ответов, поэтому я прошу прощения за любой случайный плагиат. Дайте мне знать, если вы увидите это, и я правильно подтвердю.

Предполагая, что вы счастливы вернуть LinkedList , вы можете использовать ImmutableList в качестве cdr в этом примере.

весь принцип операции cons заключается в том, что она работает со связанным списком.

public <E> LinkedList<E> cons(E car, List<E> cdr) {
    LinkedList<E> destination = new LinkedList<E>(cdr);
    destination.addFirst(car);
    return destination;
}

Обратите внимание, что приведенный выше код был написан после прочтения приведенных выше ответов, поэтому я прошу прощения за любой случайный плагиат. Дайте мне знать, если вы увидите это, и я правильно подтвердю.

Предполагая, что вы счастливы вернуть LinkedList , вы можете использовать ImmutableList в качестве cdr в этом примере.

весь принцип операции cons заключается в том, что она работает со связанным списком.

public <E> LinkedList<E> cons(E car, List<E> cdr) {
    LinkedList<E> destination = new LinkedList<E>(cdr);
    destination.addFirst(car);
    return destination;
}

Обратите внимание, что приведенный выше код был написан после прочтения приведенных выше ответов, поэтому я прошу прощения за любой случайный плагиат. Дайте мне знать, если вы увидите это, и я правильно подтвердю.

Предполагая, что вы счастливы вернуть LinkedList , вы можете использовать ImmutableList в качестве cdr в этом примере.

3
ответ дан 18 December 2019 в 05:29
поделиться

Конечно, LinkedList был бы наиболее эффективным способом вставки элемента в начало списка?

Просто используйте класс LinkedList , который поставляется с Java

2
ответ дан 18 December 2019 в 05:29
поделиться

Еще один вариант, если у вас есть только Iterable.

public static <E> List<E> cons(E e, Iterable<E> iter) {
   List<E> list = new ArrayList<E>();
   list.add(e);
   for(E e2: iter) list.add(e2);
   return list;
}

public static <E> List<E> cons(Iterable<E>... iters) {
   List<E> list = new ArrayList<E>();
   for(Iterable<E> iter: iters) for(E e1: iter1) list.add(e1);
   return list;
}
0
ответ дан 18 December 2019 в 05:29
поделиться

Я собираюсь бросить свои 2 цента, а потом посмотрю, не придумает ли кто-нибудь что-нибудь более элегантное. В общем случае:

<E> List<E> cons(E e, List<E> list) {
    List<E> res = Lists.newArrayListWithCapacity(list.size() + 1);
    res.add(e);
    res.addAll(list);
    return res;
}

С ImmutableList (не знаю, насколько это эффективно):

<E> ImmutableList<E> cons(E e, ImmutableList<E> list) {
    return ImmutableList.<E>builder()
                        .add(e)
                        .addAll(list)
                        .build();
}
2
ответ дан 18 December 2019 в 05:29
поделиться

Я считаю, что ответ, который вы действительно ищете, таков:

http://functionaljava.googlecode.com/svn/artifacts/2.20/javadoc/fj/data/List. html

Этот метод даже называется cons .

У меня нет опыта работы с этой библиотекой. Только что слышал об этом на днях. Надеюсь, все хорошо!

4
ответ дан 18 December 2019 в 05:29
поделиться

Эффективным решением было бы создать собственную реализацию списка с ленивым делегированием. Если его нельзя изменить, это не составит особого труда. Если он создан с помощью фабричного метода, вы даже можете использовать одну из двух различных базовых реализаций в зависимости от того, реализует ли список аргументов RandomAccess или нет.

Для простейшего случая (не проверял, компилируется ли это, нет проверок работоспособности и т. Д.):

class ConsList<E> extends AbstractList<E>
{
    private final E first;
    private final List<E> rest;

    ConsList( E first, List<E> rest )
    {
        this.first = first;
        this.rest = rest;
    }

    public int get( int index )
    {
        return (index == 0) ? first : rest.get( index - 1 );
    }

    public int size()
    {
        return rest.size() + 1;
    }
}

Я уверен, что некоторые другие методы можно было бы сделать более эффективными, и последовательный случай мог бы быть лучше, если вместо этого расширить AbstractSequentialList.

4
ответ дан 18 December 2019 в 05:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: