Персистентные структуры данных в Java

Заголовок Content-Encoding является заголовком ответа, который предоставляет сервер.

Обычно клиент предоставляет заголовок Accept-Encoding, чтобы указать, какую кодировку контента вы хотите запросить.

Например: Accept-Encoding: gzip, deflate

См. MDN на Сжатие с помощью gzip

Однако этот конкретный заголовок помечен как запрещенный заголовок , что означает это не может быть установлено программно Javascript, который выполняется в браузере (однако все еще работает в Node).

Большинство браузеров автоматически добавляют заголовок Accept-Encoding, содержащий все кодировки контента, которые он поддерживает.

16
задан 4 revs, 2 users 94% 21 October 2009 в 20:50
поделиться

7 ответов

Полагаю, очевидные варианты:

o Переключиться на временную структуру данных (компоновщик) для обновления. Это вполне нормально. StringBuilder для манипуляции String . Как ваш пример.

Person p3 =
    Builder.update(p)
    .withAddress(
        Builder.update(p.address())
       .withCity("Berlin")
       .build()
    )
    .build();

o Всегда используйте постоянные структуры. Несмотря на то, что копирование выглядит много, на самом деле вы должны делиться почти всеми состояниями, так что это далеко не так плохо, как кажется.

final Person p3 = p
    .withAddress(
        p.address().withCity("Berlin")
    );

o Разобрать структуру данных на множество переменных и рекомбинировать с одним огромным и запутанным конструктором.

final Person p3 = Person.of(
    p.name(),
    Address.of(
       p.house(), p.street(), "Berlin", p.country()
    ),
    p.x(),
    p.y(),
    p.z()
 );

o Использовать интерфейсы обратного вызова для предоставления новых данных. Еще более шаблонный.

final Person p3 = Person.of(new PersonInfo(
    public String  name   () { return p.name(); )
    public Address address() { return Address.of(new AddressInfo() {
       private final Address a = p.address();
       public String house  () { return a.house()  ; }
       public String street () { return a.street() ; }
       public String city   () { return "Berlin"   ; }
       public String country() { return a.country(); }
    })),
    public Xxx     x() { return p.x(); }
    public Yyy     y() { return p.y(); }
    public Zzz     z() { return p.z(); }
 });

o Используйте мерзкие хаки, чтобы сделать поля временно доступными для кода.

final Person p3 = new PersonExploder(p) {{
    a = new AddressExploder(a) {{
        city = "Berlin";
    }}.get();
}}.get();

(Как ни странно, я только что написал Крис Окасаки, «Чисто функциональные структуры данных»).

7
ответ дан 30 November 2019 в 17:05
поделиться

Очень трудно, если не невозможно, сделать вещи неизменными, если они не предназначены.

Если Вы можете создавать с нуля:

  • использовать только конечные поля
  • не ссылаться на неизменяемые объекты
1
ответ дан 30 November 2019 в 17:05
поделиться

Взгляните на Функциональную Java . В настоящее время предоставляются постоянные структуры данных:

  • Односвязный список (fj.data.List)
  • Ленивый односвязный список (fj.data.Stream)
  • Непустой список (fj.data.NonEmptyList)
  • Необязательное значение (контейнер длиной 0 или 1) (fj.data.Option)
  • Set (fj.data.Set)
  • Многоходовое дерево (иначе розовое дерево) (fj.data.Tree)
  • Неизменяемая карта (fj.data.TreeMap)
  • Продукты (кортежи) арности 1-8 (fj.P1..P8)
  • Векторы арности 2-8 (fj.data.vector.V2..V8 )
  • Указанный список (fj.data.Zipper)
  • Указанное дерево (fj.data.TreeZipper)
  • Типобезопасный, универсальный гетерогенный список (fj.data.hlist.HList)
  • Неизменяемые массивы ( fj.data.Array)
  • Тип данных о непересекающемся объединении (fj.data.Either)

Ряд примеров использования предоставляется с двоичным распределением.

6
ответ дан 30 November 2019 в 17:05
поделиться

Следуйте очень простой процедуре с динамическим прокси:

class ImmutableBuilder {

    static <T> T of(Immutable immutable) {
        Class<?> targetClass = immutable.getTargetClass();
        return (T) Proxy.newProxyInstance(targetClass.getClassLoader(),
            new Class<?>[]{targetClass},
            immutable);
    }

    public static <T> T of(Class<T> aClass) {
        return of(new Immutable(aClass, new HashMap<String, Object>()));
    }
}

class Immutable implements InvocationHandler {

    private final Class<?> targetClass;
    private final Map<String, Object> fields;

    public Immutable(Class<?> aTargetClass, Map<String, Object> immutableFields) {
        targetClass = aTargetClass;
        fields = immutableFields;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("toString")) { 
            // XXX: toString() result can be cached
            return fields.toString();
        }

        if (method.getName().equals("hashCode")) { 
            // XXX: hashCode() result can be cached
            return fields.hashCode();
        }

        // XXX: naming policy here
        String fieldName = method.getName(); 

        if (method.getReturnType().equals(targetClass)) {
          Map<String, Object> newFields = new HashMap<String, Object>(fields);
          newFields.put(fieldName, args[0]);
          return ImmutableBuilder.of(new Immutable(targetClass, newFields));
        } else {
            return fields.get(fieldName);
        }
    }

    public Class<?> getTargetClass() {
        return targetClass;
    }
}

использование:

interface Person {
    String name();
    Person name(String name);
    int age();
    Person age(int age);
}

public class Main {

    public static void main(String[] args) {
        Person mark = ImmutableBuilder.of(Person.class).name("mark").age(32);
        Person john = mark.name("john").age(24);
        System.out.println(mark);
        System.out.println(john);
    }
}

направления роста:

  • политика именования (getName, withName, name)
  • кэширование toString (), реализации hashCode ()
  • equals () должны быть простыми (хотя и не реализованными)

надеюсь, что это поможет:)

3
ответ дан 30 November 2019 в 17:05
поделиться

Хотите неизменности:

  1. , чтобы внешний код не мог изменить данные?
  2. , поэтому однажды установите значение не может быть изменено?

В обоих случаях есть более простые способы достижения желаемого результата.

Остановить внешний код от изменения данных легко с помощью интерфейсов:

public interface Person {
   String getName();
   Address getAddress();
}
public interface PersonImplementor extends Person {
   void setName(String name);
   void setAddress(Address address);
}

public interface Address {
    String getCity();
}


public interface AddressImplementor {
    void setCity(String city);
}

Затем, чтобы остановить изменение значения, как только набор также " просто »с помощью java.util.concurrent.atomic.AtomicReference (хотя может потребоваться изменить режим гибернации или какой-либо другой уровень персистентности):

class PersonImpl implements PersonImplementor {
    private AtomicReference<String> name;
    private AtomicReference<Address> address;

    public void setName(String name) {
        if ( !this.name.compareAndSet(name, name) 
           && !this.name.compareAndSet(null, name)) {
            throw new IllegalStateException("name already set to "+this.name.get()+" cannot set to "+name);
        }
    }
    // .. similar code follows....
}

Но зачем вам нужно нечто большее, чем просто интерфейсы для выполнения задачи?

0
ответ дан 30 November 2019 в 17:05
поделиться

Строители сделают ваш код слишком многословным, чтобы его можно было использовать. На практике почти все неизменяемые структуры данных, которые я видел, передаются в состоянии через конструктор. Во что бы то ни стало, вот хорошая серия публикаций, описывающих неизменяемые структуры данных в C # (которые должны легко конвертироваться в Java):

C # и Java чрезвычайно многословны, поэтому код в этих статьях довольно страшный. Я рекомендую изучить OCaml, F # или Scala и ознакомиться с неизменяемостью этих языков. Освоив эту технику, вы сможете гораздо проще применять тот же стиль кодирования к Java.

12
ответ дан 30 November 2019 в 17:05
поделиться

Я реализовал несколько постоянных структур данных на Java. Весь открытый исходный код (GPL) в коде Google для всех, кому интересно:

http://code.google.com/p/mikeralib/source/browse/#svn/trunk/Mikera/src/mikera/persistent

Основные из них:

  • Постоянный изменяемый тестовый объект
  • Постоянные хэш-карты
  • Постоянные векторы / списки
  • Постоянные наборы (включая специализированный постоянный набор целых чисел)
5
ответ дан 30 November 2019 в 17:05
поделиться
Другие вопросы по тегам:

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