В Java у меня есть массив, который содержит длинную серию иногда избыточных пар ключей, которые я хочу консолидировать в более короткий arraylist, который имеет только уникальные ключи. Как отредактировать код ниже, чтобы выполнить это?
Ниже приведен пример данных в массиве outputarr
:
key value
448 Ethanol
448 Alcohol
448 Alcohol
448 Ethanol
448 Ethanol
448 Alcohol
448 Ethanol
448 Alcohol
448 Ethyl alcohol
Я хочу объединить это в массив со следующими данными:
key value
448 Ethanol; Alcohol; Ethyl alcohol
Таким образом, 9 строк в массиве объединяются в одну строку в arraylist. И значение в arraylist представляет собой конкатенированную строку "Ethanol; Alcohol; Ethyl alcohol"
. Но каждый цифровой ключ будет иметь различное количество значений, которые должны быть объединены таким образом, чтобы создать одну строку значений, в которой перечислены уникальные имена, которые были связаны с числовым ключом в массиве.
Вот код, который у меня есть до сих пор, как его отредактировать, чтобы он выполнил то, что я описал?
private static ArrayList<ArrayList<String>> twoDimArrList = new ArrayList<ArrayList<String>>();
public void someMethod(){
int len = 1000;
String[][] outputarr = new String[len][2];
// ommitting code that populates outputarr because the next for loop is what needs help
for(int r=0;r<len;r++){
ArrayList<String> temp = new ArrayList<String>();
if(outputarr[r][0]==outputarr[r+1][0]){
if(outputarr[r][1].equalsIgnoreCase(outputarr[r+1][1])){
temp.add(outputarr[r][0]);
temp.add(outputarr[r][1]);
twoDimArrList.add(temp);
r+=1;
}
}
}
}
Существует несколько способов сделать это. Один из способов - использовать Map<Integer,Set<String>>
для хранения данных, это сопоставит ключи с наборами значений.
Затем, когда вы будете читать свои данные:
Map<Integer,Set<String>> data = new HashMap<Integer,Set<String>>();
for each item in the file {
Integer key = ...; // parsed
String value = ...; // parsed
// retrieve set if it exists, create if it doesn't.
Set<String> values = data.get(key);
if (values == null) {
values = new HashSet<String>();
data.put(key, values);
}
// add value to set
values.add(value);
}
Если вы хотите сохранить повторяющиеся значения, используйте List
вместо Set
. Если вы хотите, например, подсчитать значения, подумайте о создании нового класса, содержащего значение и его счетчик (с соответствующими реализациями equals()
, hashCode()
и/или Comparable
) и сохраните Set
из тех, которые вы обновляете как значения читаются.
Вы могли бы представить и любое количество других подходов, но в конечном итоге все сводились бы к чему-то вроде выше: сопоставьте целочисленный идентификатор с коллекцией значений.
Вы также можете немного упростить свой код, если используете один из сторонних мультиплексов, которые по существу реализуют вышеописанные функции, такие как реализация Guava или Apache Commons; К сожалению, у JDK нет встроенных мультиплексов (см. раздел "Мультимаксы" здесь).
HashMap
и HashSet
не гарантируют какого-либо конкретного заказа, когда вы перебираете значения в контейнере. Если у вас есть особые требования к заказу, TreeMap
/TreeSet
будет TreeSet
в порядке возрастания (естественный порядок, как определено Comparable
/Comparator
), а LinkedHashMap
/LinkedHashSet
сохранит порядок добавления элементов. Контейнеры выше могут быть заменены при необходимости.
Что касается итерации по данным, можно использовать стандартные методы и синтаксис, например:
for (Map.Entry<Integer,Set<String>> entry : data.entrySet()) {
Integer key = entry.getKey();
// ...
for (String value : entry.getValue()) {
// ...
}
}
Ошибка, которую вы сделали в текущей попытке вывода форматирования было полагаться на Set
по умолчанию toString()
реализации производить свой вывод. По умолчанию toString()
не может действительно угадать ваши конкретные требования, вам решать перебирать ваши данные и выпускать выходные данные, которые удовлетворяют вашим требованиям.