0

I have below ArrayList

["P", "a", "y", "P", "a", "l", "I", "n", "d", "i", "a"]

Expected result [y, l, I, n, d, i]

I want to remove all duplicates, including original value. For example: 'P' is duplicate. If i use set, it will remove duplicates and one 'P' will display. i want to remove all the 'P'.

I have tried below code. But its validating only if there is even set of chars,

ArrayList<Character> unique = new ArrayList<Character>();
for (Character c : b) {
    if (unique.contains(c)) {
        unique.remove(c);
    } else {
        unique.add(c);
    }
}

This code validates and removing 'P', but not 'a'. Because 'a' listed 3 t

stacktome
  • 790
  • 2
  • 9
  • 32
  • Why do you not want to use a map? Is this a homework assignment and is that a condition of it? Because using a map to keep a count is the natural solution to this problem. – dan.m was user2321368 Oct 08 '19 at 13:25
  • You can check this post https://stackoverflow.com/questions/27911406/java8-streams-remove-duplicates-with-stream-distinct – TheCoder Oct 08 '19 at 13:26

5 Answers5

3

First it count occurence of every char then filter out by number of occurrence (only with one occurence).

List<Character> input = Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a');

List<Character> collect = input.stream()
    .collect(Collectors.groupingBy(p -> p, Collectors.counting()))
    .entrySet().stream()
    .filter(e -> e.getValue() == 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

System.out.println(collect);

The older version without streams can be written like that:

// create Map with count occurence
Map<Character, Integer> countMap = new HashMap<>();
for (Character value : input) {
    if (!countMap.containsKey(value)) {
        countMap.put(value, 1);
    } else {
        countMap.put(value, countMap.get(value) + 1);
    }
}

// filter Map
List<Character> collect = new ArrayList<>();
for (Map.Entry<Character, Integer> value : countMap.entrySet()) {
    if( value.getValue() == 1)  {
        collect.add(value.getKey());
    }
}

System.out.println(collect);

lczapski
  • 4,026
  • 3
  • 16
  • 32
1

Try this approach:

public static void main(String[] args) {
    List<Character> unique = Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a');
    List<Character> result = unique.stream().filter(i1 -> unique.stream().filter(i2 -> i1.equals(i2)).count() == 1).collect(Collectors.toList());
    System.out.println(result);
}

Output is: [y, l, I, n, d, i]

Alexey R.
  • 8,057
  • 2
  • 11
  • 27
0

A fun way you can do this without Java 8 streams is to make an int array of size 128 that will hold the counts of each occurrence at the index of the character value.

For example, if a appears 3 times, array[97] will equal 3, where 97 is the Ascii value of a (I know technically ascii is not used).

The downside to this implementation is it cannot handle any other characters above the first 128 characters in the ascii table. Though you can extend it accordingly.

Here is what this would look like:

public static void main(String[] args) {
    ArrayList<Character> list = new ArrayList<>();
    list.add(Character.valueOf('P'));
    list.add(Character.valueOf('t'));
    list.add(Character.valueOf('L'));
    list.add(Character.valueOf('L'));
    list.add(Character.valueOf('b'));
    list.add(Character.valueOf('P'));
    list.add(Character.valueOf('c'));


    int [] lookup = new int[128];

    //Build the lookup table
    for (char c : list) {
        lookup[c]++;
    }

    //Remove the values that are greater than 1 in the lookup table
    for (int j = 0; j < lookup.length; j++) {
        int count = lookup[j];
        for (int k = 0; k < count && count > 1; k++) {
            list.remove(Character.valueOf((char) j));
        }
    }
}

The code basically breaks down to two main parts:

  • Building the lookup table.

  • Removing values from the list using the lookup table as reference.

Now this is obviously more complicated than a solution with Map, Set, or using streams would be, but I figured with your requirements you may not be able to use stream either.

Nexevis
  • 4,647
  • 3
  • 13
  • 22
0

This may help

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class RemoveDuplicates {
public static void main(String[] args) {

    String string = "PayPalIndia";

    List<Character> strings = string.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
    Set<Character> set = new HashSet<>();

    Iterator<Character> iterator = strings.iterator();
    Set<Character> invalid = new HashSet<>();
    while (iterator.hasNext()) {
        Character c = iterator.next();
        if (set.contains(c)) {
            iterator.remove();
            invalid.add(c);
        } else {
            set.add(c);
        }
    }
    System.out.println("Duplicate parents");
    invalid.forEach(System.out::print);
    System.out.println();
    strings.removeAll(invalid);

    System.out.println("=============");
    System.out.println("After removing Duplicates...");
    strings.forEach(System.out::print);
    System.out.println();
}

}

SIVA KUMAR
  • 105
  • 1
  • 2
-1

Try this

ArrayList charsList = new ArrayList<>(Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a'));

List listWithoutDuplicates = charsList.stream().distinct().collect(Collectors.toList());

Rohit
  • 339
  • 1
  • 5
  • 16
  • Please make the effort to read and understand the requirement before posting an answer... – dbl Oct 08 '19 at 14:20