Java - Filter repeats in an array of strings keeping the order

2

I'm working with Java 8.

I need, having an array of strings whose content I do not know and in which there may or may not be repetitions, obtain that content, without repetitions and without altering the original order. For example, if you had:

String[] strs = {"orange", "apple", "apple", "banana", "grape", "apple", "lemon"};

You should get:

{"orange", "apple", "banana", "grape", "lemon"};

I currently use the following method to filter repetitions, but it usually messes up the elements:

/**
 * Filters repeated strings in the array
 *
 * @param  arrStr
 * @return
 */
public static String[] filterRepeatedStr(String[] arrStr) {

    List<String> arr = Arrays.asList(arrStr);
    Set<String> hs   = new HashSet();
    hs.addAll(arr);

    return hs.toArray(new String[hs.size()]);
}
    
asked by Orici 26.06.2018 в 19:05
source

3 answers

0

The problem is the use of HashSet , the option is the use of LinkedHashSet , since LinkedHashSet stores the elements according to the order of insertion:

   String[] strs = {"orange", "apple", "apple", "banana", "grape", "apple", "lemon"};

     List<String> arr = Arrays.asList(strs);
    Set<String> hs   = new LinkedHashSet ();
    hs.addAll(arr);

As a result you would get:

   {orange, apple, banana, grape, lemon}

Something important to comment is that using HashSet has better performance but does not guarantee any order in the elements, instead LinkedHashSet yes, but performance is sacrificed.

    
answered by 26.06.2018 / 19:14
source
0

By using Stream it becomes simple.

public class FiltrarRepeticiones {
    public static void main(String[] args) {
        String[] strs = {"orange", "apple", "apple", "banana", "grape", "apple", "lemon"};
        List<String> list = Arrays.asList(strs);
        Stream<String> listaNueva = list.stream().distinct();
        listaNueva.forEach(fruta -> System.out.println(fruta));   
    } 
}
  

Result:   orange apple banana grape lemon

Update. This way you could work with the functional interfaces . I'll give an example with the interface UnaryOperator , which receives a type and returns a value of the same type.

public interface UnaryOperator<T> extends Function<T,T>

Ex:

public class UnaryOperatorTest {
    public static void main(String[] args) {
        List<String> listaStr = 
                Arrays.asList("orange", "apple", "apple", "banana", "grape", "apple", "lemon");

        List<String> listStrAct = operadorUnaryStr(cadena -> cadena.toUpperCase(), listaStr);
        listStrAct.stream().distinct().forEach(str -> System.out.print(str+" "));

    }

    public static List<String> operadorUnaryStr(
                UnaryOperator<String> unaryOpt, List<String> lista){
        List<String> listaActualizada = new ArrayList<>();
        lista.forEach(str -> listaActualizada.add(unaryOpt.apply(str)));
        return listaActualizada;  
    }

}
  

And we would get as a result ...   ORANGE APPLE BANANA GRAPE LEMON

    
answered by 26.06.2018 в 19:50
0

With Streams you can remove repeated values and have an array again without creating other collections. In addition, the Arrays library makes the work of manipulating arrays much easier.

String[] strs = {"orange", "apple", "apple", "banana", "grape","apple","lemon"};
String[] str = Arrays.stream(strs)
            .distinct()
            .toArray(String[]::new);

System.out.println(Arrays.toString(str));
    
answered by 29.06.2018 в 17:51