Подтвердить что ты не робот

Создать ArrayList уникальных значений

У меня есть ArrayList со значениями, взятыми из файла (много строк, это всего лишь выдержка):

20/03/2013 23:31:46 6870    6810    6800    6720    6860    6670    6700    6650    6750    6830    34864   34272
20/03/2013 23:31:46 6910    6780    6800    6720    6860    6680    6620    6690    6760    6790    35072   34496

Где первые два значения в строке - это строки, которые содержат данные и хранятся в одном элементе.

Я хочу сравнить элементы данных строки и удалить, например, второй элемент и все элементы, указанные в этой строке.

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

Мой вопрос: могу ли я реализовать другие лучшие решения?

Это мой код:

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
    public static void main(String[] args) throws Exception{

        //The input file
        Scanner s = new Scanner(new File("prova.txt"));

        //Saving each element of the input file in an arraylist 
        ArrayList<String> list = new ArrayList<String>();
        while (s.hasNext()){
            list.add(s.next());
        }
        s.close();

        //Arraylist to save modified values
        ArrayList<String> ds = new ArrayList<String>();

        //
        int i;
        for(i=0; i<=list.size()-13; i=i+14){

            //combining the first to values to obtain data  
            String str = list.get(i)+" "+list.get(i+1);
            ds.add(str);
            //add all the other values to arraylist ds
            int j;
            for(j=2; j<14; j++){
                ds.add(list.get(i+j));
            }

            //comparing data values
            int k;  
            for(k=0; k<=ds.size()-12; k=k+13){
                ds.get(k); //first data string element  
                //Comparing with other strings and delete
                //TODO  
            }
        }
    }
}
4b9b3361

Ответ 1

Создайте Arraylist уникальных значений

Вы можете использовать метод Set.toArray().

Коллекция, которая не содержит повторяющихся элементов. Более формально, наборы не содержат пары элементов e1 и e2 таких, что e1.равнения (e2) и at самый один нулевой элемент. Как видно из названия, эти интерфейсные модели математическая установка абстракции.

http://docs.oracle.com/javase/6/docs/api/java/util/Set.html

Ответ 2

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

Он будет выглядеть примерно так.

   if(!list.contains(data))
       list.add(data);

Это должно предотвратить дублирование в списке, а также не испортить порядок элементов, как будто люди ищут.

Ответ 3

HashSet hs = new HashSet();
                hs.addAll(arrayList);
                arrayList.clear();
                arrayList.addAll(hs);

Ответ 4

 //Saving each element of the input file in an arraylist 
    ArrayList<String> list = new ArrayList<String>();
    while (s.hasNext()){
        list.add(s.next());
    }

//That all you need
list = (ArrayList) list.stream().distinct().collect(Collectors.toList());

Ответ 5

Вы можете использовать Set. Это коллекция, которая не принимает дубликаты.

Ответ 6

Используйте Set

      ...
      Set<String> list = new HashSet<>();
      while (s.hasNext()){
         list.add(s.next());
      }
      ...

Ответ 7

Довольно поздно на вечеринку, но вот мои два цента

Используйте LinkedHashSet

Я предполагаю, что вам нужна коллекция, которая:

  • запрещает вам вставлять дубликаты;
  • сохраняет порядок вставки.

LinkedHashSet делает это. Преимуществом по сравнению с использованием ArrayList является то, что LinkedHashSet имеет сложность O (1) для contains операции, в отличие от ArrayList, который имеет O (N).


Конечно, вам нужно правильно реализовать ваши методы equals и hashCode.

Ответ 8

Вы можете легко сделать это с помощью Hashmap. У вас, очевидно, есть ключ (который является строковыми данными) и некоторые значения.

Прокрутите все ваши строки и добавьте их на свою карту.

Map<String, List<Integer>> map = new HashMap<>();
...
while (s.hasNext()){
  String stringData = ...
  List<Integer> values = ...
  map.put(stringData,values);
}

Обратите внимание, что в этом случае вы сохраните последнее наличие повторяющихся строк. Если вы предпочитаете удерживать первый и удалять другие, вы можете добавить чек с помощью Map.containsKey(String stringData); перед тем, как положить карту.

Ответ 9

Просто переопределить метод boolean equals() настраиваемого объекта. Скажем, у вас есть ArrayList с настраиваемым полем f1, f2,... override

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof CustomObject)) return false;

    CustomObject object = (CustomObject) o;

    if (!f1.equals(object.dob)) return false;
    if (!f2.equals(object.fullName)) return false;
    ...
    return true;
}

и проверить, используя метод экземпляра ArrayList contains(). Что это.

Ответ 10

Если вам нужны уникальные значения, вы должны использовать реализацию интерфейса SET

Ответ 11

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

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

        int i = 0;
        String lastData = null;
        while (s.hasNext()) {
            String str = s.next();
            if (i % 13 == 0) {
                if (map.containsKey(str)) {
                    //skip the whole row
                    lastData = null;
                } else {
                    lastData = str;
                    map.put(lastData, new ArrayList<String>());
                }
            } else if (lastData != null) {
                map.get(lastData).add(str);
            }


            i++;
        }

Ответ 12

Я использую вспомогательный класс. Не уверен, хорошо это или плохо

public class ListHelper<T> {
    private final T[] t;

    public ListHelper(T[] t) {
        this.t = t;
    }

    public List<T> unique(List<T> list) {
       Set<T> set = new HashSet<>(list);
        return Arrays.asList(set.toArray(t));
    }
}

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

import static org.assertj.core.api.Assertions.assertThat;


public class ListHelperTest {

    @Test
    public void unique() {
        List<String> s = Arrays.asList("abc", "cde", "dfg", "abc");
        List<String> unique = new ListHelper<>(new String[0]).unique(s);
        assertThat(unique).hasSize(3);
    }
}

Или версия Java8:

public class ListHelper<T> {
    public Function<List<T>, List<T>> unique() {
        return l -> l.stream().distinct().collect(Collectors.toList());
    }
}

public class ListHelperTest {
    @Test
    public void unique() {
        List<String> s = Arrays.asList("abc", "cde", "dfg", "abc");
        assertThat(new ListHelper<String>().unique().apply(s)).hasSize(3);
    }
}

Ответ 13

Решение № 1: HashSet

Хорошее решение немедленной проблемы чтения файла в ArrayList с ограничением уникальности - просто сохранить HashSet видимых элементов. Перед обработкой строки мы проверяем, что ее ключа еще нет в наборе. Если это не так, мы добавляем ключ в набор, чтобы пометить его как завершенный, а затем добавляем данные строки в результат ArrayList.

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) 
        throws FileNotFoundException, IOException {

        String file = "prova.txt";
        ArrayList<String[]> data = new ArrayList<>();
        HashSet<String> seen = new HashSet<>();

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            for (String line; (line = br.readLine()) != null;) {
                String[] split = line.split("\\s+");
                String key = split[0] + " " + split[1];

                if (!seen.contains(key)) {
                    data.add(Arrays.copyOfRange(split, 2, split.length));
                    seen.add(key);
                }
            }
        }

        for (String[] row : data) {
            System.out.println(Arrays.toString(row));
        }
    }
}

Решение № 2: LinkedHashMap/LinkedHashSet

Поскольку у нас есть пары ключ-значение в этом конкретном наборе данных, мы можем свернуть все в LinkedHashMap<String, ArrayList<String>> (см. Документы по LinkedHashMap), который сохраняет порядок, но не может быть проиндексирован в (управляемый сценарием использования решение, но соответствует той же стратегии, что и выше. ArrayList<String> или String[] здесь произвольно - это может быть любое значение данных). Обратите внимание, что в этой версии легко сохранить самый последний увиденный ключ, а не самый старый (удалите тест !data.containsKey(key)).

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) 
        throws FileNotFoundException, IOException {

        String file = "prova.txt";
        LinkedHashMap<String, ArrayList<String>> data = new LinkedHashMap<>();

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            for (String line; (line = br.readLine()) != null;) {
                String[] split = line.split("\\s+");
                String key = split[0] + " " + split[1];

                if (!data.containsKey(key)) {
                    ArrayList<String> val = new ArrayList<>();
                    String[] sub = Arrays.copyOfRange(split, 2, split.length); 
                    Collections.addAll(val, sub);
                    data.put(key, val);
                }
            }
        }

        for (Map.Entry<String, ArrayList<String>> e : data.entrySet()) {
            System.out.println(e.getKey() + " => " + e.getValue());
        }
    }
}

Решение № 3: ArrayListSet

Приведенные выше примеры представляют довольно узкие варианты использования. Вот набросок для общего класса ArrayListSet, который поддерживает обычное поведение списка (add/set/remove и т.д.) При сохранении уникальности.

По сути, этот класс является абстракцией решения № 1 в этом посте (HashSet в сочетании с ArrayList), но с несколько иной разновидностью (сами данные используются для определения уникальности, а не ключа, но это правда " ArrayList "структура).

Этот класс решает проблемы эффективности (ArrayList#contains является линейным, поэтому мы должны отклонить это решение, кроме как в тривиальных случаях), отсутствие упорядоченности (хранение всего непосредственно в HashSet не помогает нам), отсутствие операций ArrayList (LinkedHashSet в противном случае является лучшим решением, но мы не можем индексировать его, поэтому он не является истинной заменой ArrayList).

Использование HashMap<E, index> вместо HashSet ускорит функции remove(Object o) и indexOf(Object o) (но замедлит sort). Линейный remove(Object o) является основным недостатком над равниной HashSet.

import java.util.*;

public class ArrayListSet<E> implements Iterable<E>, Set<E> {
    private ArrayList<E> list;
    private HashSet<E> set;

    public ArrayListSet() {
        list = new ArrayList<>();
        set = new HashSet<>();
    }

    public boolean add(E e) {
        return set.add(e) && list.add(e);
    }

    public boolean add(int i, E e) {
        if (!set.add(e)) return false;
        list.add(i, e);
        return true;
    }

    public void clear() {
        list.clear();
        set.clear();
    }

    public boolean contains(Object o) {
        return set.contains(o);
    }

    public E get(int i) {
        return list.get(i);
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public E remove(int i) {        
        E e = list.remove(i);
        set.remove(e);
        return e;
    }

    public boolean remove(Object o) {        
        if (set.remove(o)) {
            list.remove(o);
            return true;
        }

        return false;
    }

    public boolean set(int i, E e) {
        if (set.contains(e)) return false;

        set.add(e);
        set.remove(list.set(i, e));
        return true;
    }

    public int size() {
        return list.size();
    }

    public void sort(Comparator<? super E> c) {
        Collections.sort(list, c);
    }

    public Iterator<E> iterator() {
        return list.iterator();
    }

    public boolean addAll(Collection<? extends E> c) {
        int before = size();
        for (E e : c) add(e);
        return size() == before;
    }

    public boolean containsAll(Collection<?> c) {
        return set.containsAll(c);
    }

    public boolean removeAll(Collection<?> c) {
        return set.removeAll(c) && list.removeAll(c);
    }

    public boolean retainAll(Collection<?> c) {
         return set.retainAll(c) && list.retainAll(c);
    }

    public Object[] toArray() {
        return list.toArray();
    }

    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");

        for (int i = 0; i < list.size() - 1; i++) {
            sb.append(list.get(i) + ", ");
        }

        if (!list.isEmpty()) {
            sb.append(list.get(list.size() - 1));
        }

        sb.append("]");
        return sb.toString();
    }
}

Пример использования:

public class ArrayListSetDriver {
    public static void main(String[] args) {
        ArrayListSet<String> fruit = new ArrayListSet<>();
        fruit.add("apple");
        fruit.add("banana");
        fruit.add("kiwi");
        fruit.add("strawberry");
        fruit.add("apple");
        fruit.add("strawberry");

        for (String item : fruit) {
            System.out.print(item + " "); // => apple banana kiwi strawberry
        }

        fruit.remove("kiwi");
        fruit.remove(1);
        fruit.add(0, "banana");
        fruit.set(2, "cranberry");
        fruit.set(0, "cranberry");
        System.out.println();

        for (int i = 0; i < fruit.size(); i++) {
            System.out.print(fruit.get(i) + " "); // => banana apple cranberry
        }

        System.out.println();
    }
}