Эффективное хранение массива объектов, содержащих примитивы в Java

#java #c #arrays

#java #c #массивы

Вопрос:

Какой наиболее эффективный способ преобразовать следующую структуру данных из C в Java?

 struct {
  int a; int b; int c; int d;
  double e;
} foo[] = {
  { 0, 1, 2, 42, 37.972},
  /* ... 100 more struct elements ... */,
  { 0, 3, -1, -4, -7.847}
}
  

Лучшее, что я мог придумать, это:

 class Foo {
    public int a;
    public int b;
    public int c;
    public int d;
    public double e;
    public Foo(int a, int b, int c, int d, double e) {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.e = e;
    }
}

Foo[] foo = new Foo[] {
    new Foo(0, 1, 2, 42, 37.972),
    /* ... 100 more objects ... */
    new Foo(0, 3, -1, -4, -7.847)
}
  

Но он использует слишком много объектов для хранения простых примитивов.

Ответ №1:

Но он использует слишком много объектов для хранения простых примитивов.

Нет, это не так. Java int или double поле не является объектом; оно будет размещено в куче как часть содержащего Foo его экземпляра.

Итак, в вашем случае будет 101 объект: один Foo[] массив и 100 Foo экземпляров.

Или вы хотите, чтобы все это было одним «плоским» массивом? Извините, на Java это невозможно, так это не работает.

Опять же, о чем именно вы беспокоитесь здесь? 101 Объект такого рода — это ничто, мы говорим здесь о менее чем 4 КБ!

Комментарии:

1. Да, я надеялся, что смогу сделать его плоским вместо использования 101 объекта. Это так просто сделать на C.

2. @Dheeraj: ну, если вам нужен C, вы знаете, где его найти… Серьезно, в чем проблема? Служебный объем объекта составляет 8 байт. Поскольку ваши примеры объектов имеют полезную нагрузку в 24 байта, это накладные расходы на 33%. Не идеально, но вряд ли драматично, и, конечно, не стоит беспокоиться, если у вас нет миллионов объектов (и даже тогда поиск способа уменьшить это число может быть гораздо более эффективным).

3. Спасибо за информацию. Исходя из встроенного фона C, я был параноиком.

4. @Dheeraj: Ах, это все объясняет 🙂

Ответ №2:

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

Но с этим будет намного сложнее справиться, и вы можете слишком легко вводить ошибки, кроме того, что это не очень похоже на OO (т. Е. Вы не можете легко использовать полезные функции, которые Java предоставляет с такой конструкцией).

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

Если вы используете подход с параллельными массивами, то вы можете создать Foo класс, который действует как фасадный объект для этих массивов: он принимает индекс i и действует так, как если бы это была единая структура, прозрачно ссылаясь на соответствующие массивы.

Ответ №3:

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

 int[] a = new int[] { 0, ..., 0 };
int[] b = new int[] { 1, ..., 3 };
int[] c = new int[] { 2, ..., -1 };
int[] d = new int[] { 42, ..., -4 };
double[] e = new double[] { 37.972, ..., -7.847 };
  

Ответ №4:

Перефразируя ваш вопрос: «Хранение массива объектов, содержащих примитивы в Java, эффективно». Вы даже не должны задавать себе такие вопросы: массивы, коллекции и объекты — это правильный путь, используйте их без запоздалой мысли.

Ответ №5:

Я бы сказал: не беспокойтесь об этом.

Размер объекта Foo в 32-разрядной виртуальной машине равен

8 байт служебных данных объекта 4 * (4 байта для полей int) 1 * (8 байт для двойных полей) = 32 байта

Таким образом, накладные расходы на объект составляют 25%. Существуют способы эффективного использования памяти с буферами Java NIO, но это редко стоит того, если вы не имеете дело с огромными объемами данных.

Ответ №6:

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

Ответ №7:

Вы можете найти онлайн-конвертер или написать простую программу, которая использует регулярное выражение для сбора данных из исходного файла c и генерации кода Java.