Запрос на объект Java без базы данных

Примечание: Маленький длинный вопрос. Я собираюсь дать щедрость за лучший ответ.

То, что я пытаюсь сделать, это запрос объекта. Вот подробности. У меня есть файл с именем employee.txt. Поэтому я проанализировал его и сохранил в списке

public static List<Employee> employeeList = new LinkedList<>();

Тогда вот моя логика для запроса.

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

Для примера: вот запрос

select * from Employee where id > 10

Мои коды для этого

String valueToCompare = split[5];  //10
EmployeeCriteria criteria = new EmployeeCriteria(
        isId, isName, isSalary, expression,
        valueToCompare);
result = EmployeeData.findAll(
        EmployeeData.employeeList, criteria);

Вот метод findAll

public static List<Employee> findAll(List<Employee> coll,
            ISearch<Employee> chk) {
        List<Employee> l = new LinkedList<Employee>();
        for (Employee obj : coll) {
            if (chk.search(new Employee(obj)))
                l.add(obj);
        }
        return l;
    }

И вот мой метод поиска

/**
     * Based on the type provided and for given expression it check against the
     * given value
     */

    @Override
    public boolean search(Employee obj) {
        if (expression.equals(EQUAL)) {
            if (isId()) {
                if (obj.getId() == Long.parseLong(valueToCompare)) {
                    return true;
                }
            } else if (isName()) {
                if (obj.getName().equals(valueToCompare)) {
                    return true;
                }
            } else if (isSalary()) {
                if (obj.getSalary() == Long.parseLong(valueToCompare)) {
                    return true;
                }
            } else {
                System.err.println(UserMessage.INVALIDCOLUMN_NAME);
            }

        } else if (expression.equals(NOT_EQUAL)) {
            if (isId()) {
                if (!(obj.getId() == Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else if (isName()) {
                if (!(obj.getName().equals(valueToCompare))) {
                    return true;
                }
            } else if (isSalary()) {
                if (!(obj.getSalary() == Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else {
                System.err.println(UserMessage.INVALIDCOLUMN_NAME);
            }

        } else if (expression.equals(GREATER)) {
            if (isId()) {
                if ((obj.getId() > Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else if (isSalary()) {
                if ((obj.getSalary() > Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else {
                System.err.println(UserMessage.INVALIDCOLUMN_NAME);
            }

        } else if (expression.equals(LESSER)) {
            if (isId()) {
                if ((obj.getId() < Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else if (isSalary()) {
                if ((obj.getSalary() < Long.parseLong(valueToCompare))) {
                    return true;
                }
            } else {
                System.err.println(UserMessage.INVALID_IDENTIFIER);
            }

        }

        return false;
    }

Сообщите мне, хотите ли вы видеть другие коды.

Я просто хочу знать,

Во-первых, LinkedList - правильная структура данных для использования? Это хорошо работает? Любые улучшения для наилучшего выполнения?

Есть ли лучший способ добиться этого?

Вот несколько примеров:

select * where ID > 100
select * where Name != Ramesh
select * where Salary < 500000
select Name order by Name
select ID

Спасибо за любую помощь. Bounty будет предложено через 2 дня. Я не могу этого сделать сейчас.

Примечание2: Это тест для проверки навыков управления данными, и я не могу использовать какую-либо базу данных.

Ответы

Ответ 1

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

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

Предполагая, что это не для производства, и вы просто развлекаетесь, тогда вы хотите подражать тем, что делают базы данных в реальной жизни. Они создают индексы. Индексы обычно лучше всего описываются как Map<String, List<Employee>>.

Идея состоит в том, что изначально чтение данных с диска дорого. Но вы читали его один раз. Для каждого измерения Name, Salary, ID и т.д.... вы хотите создать отдельные индексы.

Итак, скажем, вы создавали индекс всех сотрудников по ID. Вы хотели бы сделать что-то вроде:

Map<String, Employee> employeesById = new HashMap<>();

for(Employee e : employees) { 
  employeesById.put(e.getId(), e);
}

Вышеприведенное предполагает, что идентификаторы сотрудников уникальны. Если это не так, вам нужно создать List<Employee>. Например, для индекса по имени:

Map<String,List<Employee>> employeesByName = new HashMap<>();

for(Employee e : employees) { 
  employeesByName.get(e.getName()).add(e); // Make sure to create the array if it doesn't exist
}

Итак, теперь, для чтения, скажем, вы получите SELECT * FROM employees where id = 123;, просто можете просто вернуть employeesById.get("123").

Это решение O(1). По мере увеличения размера файла у вас не будет потери производительности. Это, вероятно, самое быстрое решение.

Ответ 2

Чтобы добавить ответ Амира, вы также можете использовать TreeMap<> вместо HashMap<>. Базы данных обычно не создают индексы как хеш-карты, а как сбалансированные двоичные деревья, что и есть класс Java TreeMap<>.

http://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html

HashMap<> имеет O (1) поиск ключей, но является точным совпадением только с ключом. TreeMap<> имеет O (log n) поиск по ключам, но позволяет поиск по диапазону higherKey, lowerKey) и разбиение на разделы по диапазону клавиш (subMap).

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

Ответ 3

Предполагая, что вас не интересует какое-либо из решение для базы данных в памяти и с использованием Java 8, Вы должны преобразовать все свои условия в предикат и применить их к потоку. Это позволит использовать функцию Java 8 parallelism http://blog.takipi.com/new-parallelism-apis-in-java-8-behind-the-glitz-and-glamour/

Короче говоря, ваш код может быть намного чище и быстрее

 public static Predicate<Employee> isSalaryGreaterThan(Integer salary) {
        return p -> p.getSalary() > salary;
    }

Predicate predicate1 =   isSalaryGreaterThan(50000)
    employeeList.stream().filter(predicate1).filter(predicate2)...collect(Collectors.<Employee>toList())