#java #indexing #matrix
#java #индексирование #матрица
Вопрос:
Я хотел знать, возможно ли проиндексировать несколько столбцов матрицы для ускорения сортировки. В MySQL вы можете иметь индексы по нескольким столбцам, что ускоряет поиск элементов в таблице, но я не знаю, возможно ли это в стандартной матрице Java. Например, мои данные представляют собой матрицу из 3 столбцов, которая содержит идентификатор, имя и фамилию, а затем множество записей в этой таблице. Прямо сейчас я могу произнести что-то вроде mat[5] и получить запись для пользователя с идентификатором 5, но я также хочу иметь возможность искать записи по столбцу фамилии. Как я могу сделать это наиболее эффективно на Java?
Ответ №1:
Если это Java, вы всегда можете настроить хэш-таблицу, которая связывает фамилии с массивом индексов строк матрицы, так что люди в этих строках будут иметь эту фамилию.
Или у вас может быть многоуровневая хэш-таблица, такая, что вы можете сделать m[index.get(lastName).get(firstName)]
.
Кроме того, если вы хотите перебирать имена в лексикографическом порядке, вы можете заменить хэш-таблицу на TreeMap
.
Пример:
import java.util.*;
class Test{
public static void main(String[]args){
Object[][] m = new Object[][]{
{1, "Smith", "John"},
{2, "Stone", "Jack"},
{3, "Stein", "Robert"},
{4, "Stone", "Bob"}
};
//index.get(lastName) will return a map between
//first names and matrix row indices.
//index.get(lastName).get(firstName) returns the index
//in the matrix of the row pertaining to person (lastName, firstName)
TreeMap<String, TreeMap<String, Integer>> index =
new TreeMap<String, TreeMap<String, Integer>>();
//create index
for(int i=0;i<m.length;i ){
Object[]o = m[i];
String last = o[1].toString();
String first = o[2].toString();
TreeMap<String,Integer> index2 = index.get(last);
if (index2==null){
index2=new TreeMap<String,Integer>();
index.put(last, index2);
}
index2.put(first, i);
}
System.out.print("Smith, John -> ");
System.out.println(Arrays.toString(m[index.get("Smith").get("John")]));
System.out.print("Stone -> ");
System.out.println(index.get("Stone"));
System.out.print("Full index: ");
System.out.println(index);
}
}
Вывод:
Smith, John -> [1, Smith, John]
Stone -> {Bob=3, Jack=1}
Full index: {Smith={John=0}, Stein={Robert=2}, Stone={Bob=3, Jack=1}}
В примере, который я привел, недостаточно сопоставить фамилии с индексами строк, потому что у вас могут быть два человека с одинаковыми фамилиями. Однако я сделал предположение, что у вас не будет двух пользователей с одинаковым именем. В противном случае вам понадобилось бы что-то вроде TreeMap<String, TreeMap<String, ArrayList<Integer>>>
, чтобы иметь возможность находить всех с заданным (фамилия, имя).
Если вы хотите выполнить поиск по идентификатору, вам просто нужно создать второй индекс, сопоставляющий идентификаторы индексам строк, которым может быть HashMap<Integer, Integer>
.
В этом небольшом примере от наличия индексов мало что выиграет, поскольку они, вероятно, занимают больше места, чем сама матрица, но это, вероятно, окупается, если ваши записи большие.
Комментарии:
1. эй, извините, я не совсем понимаю, как вы могли бы реализовать свое предложение. Если у меня есть массив, и каждый слот указывает на хэш, и каждый из ключей в этих хэшах указывает на другие хэши, как это позволит мне выполнять поиск по фамилиям? Допустим, записи являются
1 - Smith, John
,2 - Stone, Jack
,3 - Stein, Robert
. Можете ли вы показать мне, как я мог бы выполнить поиск второй записи как по ее идентификатору (2), так и по фамилии (Stone), используя ваш код?
Ответ №2:
В общем, если вам требуется более одного способа доступа к структуре данных Java, вам придется создавать дополнительные, «параллельные» структуры.
Например, у вас может быть ваша «основная таблица» — будь то массив, список или что-то еще, — которая сортируется или вводится по имени. Затем вы создали бы вторую таблицу, отсортированную, скажем, по номеру клиента, и каждая запись в этой таблице могла бы содержать индекс первой таблицы или другую копию дескриптора объекта. Тогда у вас могла бы быть третья таблица, отсортированная по дате рождения, записи которой также указывают на первую таблицу и т.д.
Например:
class Customer
{
public String name;
public int customerNumber;
public int shoeSize;
... whatever ...
}
class byName implements Comparator<Customer>
{
public int compareTo(Customer c1, Customer c2)
{
return c1.name.compareTo(c2.name);
}
}
class byShoeSize implements Comparator<Customer>
{
public int compareTo(Customer c1, Customer c2)
{
return c1.shoeSize-c2.shoeSize;
}
}
... elsewhere ...
Customer[] nameOrder=new Customer[100];
nameOrder[0]=new Customer("Fred Smith", 10001, 9);
nameOrder[1]=new Customer("Mary Jones", 10002, 7);
... etc, however we get the list initialized ...
Arrays.sort(nameOrder, byName);
Customer[] shoeSizeOrder=new Customer[100];
for (int n=0;n<customerList.length; n)
byNumber[n]=customerList[n];
Arrays.sort(shoeSizeOrder, byShoeSize);
(Обычный отказ от ответственности: непроверенный код у меня в голове. Пожалуйста, извините за любые синтаксические ошибки. Проверка ошибок опущена и другие упрощения, чтобы дать представление. И т.д.)
После этого у вас будет один список, отсортированный по имени, а другой список, отсортированный по размеру обуви. Затем вы могли бы просмотреть каждый список по порядку, выполнить двоичный поиск для нахождения определенных значений и т.д.
Конечно, ничто не говорит, что все списки должны быть массивами. Это могут быть хэш-таблицы, списки массивов или любая другая структура, которая либо упорядочена, либо имеет сопоставление ключ / значение.
Обратите внимание, что это не две копии одних и тех же данных. Существует только один набор объектов. У нас просто есть два ДЕСКРИПТОРА для каждого объекта, по одному в каждом списке.