2015-12-16 24 views
10

Chcę dodać litery String do listy, ale chcę dodać tylko jedną literę raz. Na przykład, jeśli ciąg brzmi "HELLO AM CHRISTOS WHITE", niektóre litery pojawiają się więcej niż jeden raz, więc chcę, aby były dodawane tylko jeden raz.Dodaj unikalne litery danego ciągu do listy

myślę o dwóch pętli:

for (int i=0; i< str.length(); i++){ 
    for(int j=0; j< str.length(); j++){ 
     if (str.charAt(i) != str.charAt(j)) { 
      myList.add(charAt(i)); 
     } 
    } 
} 

Ale ten kod nie uniknąć duplikatów.

+0

Dlaczego dwie pętle? iteruj na pojedynczym originalLine.toCharArray(); if (! listContains (Char.valueOf (char [i])) addChar(); – Stultuske

+3

Alternatywnie, możesz użyć 'Set', aby osiągnąć wyjątkowość jego treści –

Odpowiedz

14

byłoby bardziej efektywne użycie LinkedHashSet określania unikalnych znaków. Jeśli użyjesz LinkedHashSet, kolejność unikalnych znaków wejściowego łańcucha zostanie zachowana.

Po pojedynczej pętli, która zajęłaby czas liniowy, można dodać wszystkie unikalne znaki do wyjścia List.

Set<Character> unique = new LinkedHashSet<>(); 
for (int i = 0; i < str.length(); i++){ 
    unique.add(str.charAt(i)); 
} 
myList.addAll(unique); 
12

Aby zapobiec duplikatom w kolekcji, nie potrzebujesz List, potrzebujesz Set (np. HashSet).

Jeśli chcesz zachować porządek, do którego dodajesz swoje String s, użyj numeru LinkedHashSet.

Wreszcie, jeśli chcesz Set naturalnie posortować String s (lub móc sortować je Comparator), użyj TreeSet.

Przykład

String foo = "ghghababcdef"; 
Set<String> hash = new HashSet<>(); 
Set<String> linked = new LinkedHashSet<>(); 
Set<String> tree = new TreeSet<>(); 
// iterating characters 
for (char c: foo.toCharArray()) { 
    // adding String representation of character to each set 
    hash.add(Character.toString(c)); 
    linked.add(Character.toString(c)); 
    tree.add(Character.toString(c)); 
} 
// printing... 
System.out.println(hash); 
System.out.println(linked); 
System.out.println(tree); 

Wyjście

[a, b, c, d, e, f, g, h] // this may vary 
[g, h, a, b, c, d, e, f] // keeps insertion order 
[a, b, c, d, e, f, g, h] // sorted lexicographically by default 
4

jako alternatywa dla Set odpowiedź, jeśli chcesz, aby trzymać się roztworem List. Wystarczy pętla jeden raz i skorzystać z metody List.contains(Object) i sprawdzić, czy bieżący char jest już obecny w twoim List.

String str = "HELLO AM CHRISTOS WHITE"; 
List<Character> myList = new ArrayList<>(); 
for(int i=0; i< str.length(); i++){ 
    if (!myList.contains(str.charAt(i))) { 
     myList.add(str.charAt(i)); 
    } 
} 
for(char c : myList) { 
    System.out.println(c); 
} 

wyjście

HELO AMCRISTW

0

j nie jest przypisany. Domyślam się, że jest on zainicjowany na 0, więc nie ma wyjątku

Jeśli zmienisz drugą pętlę na for(int j=0; j< str.length(); j++), to nadal nie będzie działać, nie będzie drukować żadnych liter, które są powielone w ciągu.

Pomyśl o tym, jaki zakres j musi powtórzyć. Chcesz wydrukować dowolną literę, która jeszcze nie pojawiła się w ciągu znaków, jeśli otrzymasz mój jist.

+0

To był tylko przykład w moim programie jest poprawny. i tak było i tak –

+0

@ ChristosMichael: W takim przypadku dobrym pomysłem byłoby zaakceptowanie odpowiedzi, która najlepiej odpowiada na twoje pytanie. Pomaga to przyszłym odwiedzającym szybko zidentyfikować działające rozwiązanie ich problemu. [Zobacz, co powinienem zrobić, gdy ktoś odpowie moje pytanie?] (http://stackoverflow.com/help/someone-answers) – IInspectable

+0

Moja odpowiedź dotyczyła błędu w kodzie, który podałeś, jak mam wiedzieć, co masz w swoim programie. chciałem rozwiązać problem w zaimplementowanej logice, nie zdawałem sobie sprawy, że masz inne możliwości wykorzystania dobrze znanych struktur danych. –

0

Niestety nie ma strumień znaków w Java 8, ale tutaj jest Java 8 sposób:

str.chars().distinct().mapToObj(c -> (char) c).collect(Collectors.toList()); 

To może być mniej efektywne, ale jest czytelny jeden liner i pokazuje siłę strumieni.