mi_mo
mi_mo

Reputation: 184

Merge multiple list of string in unique list in java 8

Edit2: : I have main data(list or array,it's no matter) like this:

{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}

I want to:

1-replace all values containing 3 with "julie"

2-all values that are val % 15 == 0 should be replaced with "jack".

3-also replace all values that are val % 5 == 0 should be replaced with "john" ,

Note: Without If Else Just With Java 8.

In the end I should have this data :

("1","2","julie","4","john","6","7","8","9","john","11","12","julie","14","jack","16","17","18","19","john")

for this issue I use stream and replaced these values with related string and i created 3 related list for each string:

1-Result for need1(replace all values containing 3 with "julie"): ("1","2","julie","4","5","6","7","8","9","10","11","12","julie","14","15","16","17","18","19","20")

2-Result for need2(all values that are val % 15 == 0 should be replaced with "jack"): ("1","2","3","4","5","6","7","8","9","10","11","12","13","14","jack","16","17","18","19","20")

3-Result for need3(replace all values that are val % 5 == 0 should be replaced with "john") :("1","2","3","4","john","6","7","8","9","john","11","12","13","14","john","16","17","18","19","john")

Now I want to have a final result such as below(either with mereg these lists or any other method without If&Else just with java8): :

("1","2","julie","4","john","6","7","8","9","john","11","12","julie","14","jack","16","17","18","19","john")

Thanks!

Upvotes: 0

Views: 1287

Answers (5)

ricken_bazolo
ricken_bazolo

Reputation: 31

You can use this approach to get the result

Stream<Integer> list = Stream.of(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);
    String result = list
            .map(String::valueOf)
            .map(s -> s.equals("3") ? "julie" : s)
            .map(s -> ( StringUtils.isNumeric(s) ? ((Integer.parseInt(s)%15)==0 ? "jack":s):s))
            .map(s -> ( StringUtils.isNumeric(s) ? ((Integer.parseInt(s)%5)==0 ? "jack":s):s))
            .collect(Collectors.joining(","));
    System.out.print(result);

Console output

1,2,julie,4,jack,6,7,8,9,jack,11,12,13,14,jack,16,17,18,19,jack

Upvotes: 1

WJS
WJS

Reputation: 40044

Ok, based on your clarification I can create the final String like so.

Here is how to merge the three lists per your criteria.

String[] arr1 = { "1", "2", "julie", "4", "5", "6", "7", "8",
        "9", "10", "11", "12", "julie", "14", "15", "16",
        "17", "18", "19", "20" };
String[] arr2 = { "1", "2", "3", "4", "5", "6", "7", "8", "9",
        "10", "11", "12", "13", "14", "jack", "16", "17",
        "18", "19", "20" };
String[] arr3 = { "1", "2", "3", "4", "john", "6", "7", "8",
        "9", "john", "11", "12", "13", "14", "john", "16",
        "17", "18", "19", "john" };
  • IntStream from 0 to size of array
  • check if each array element equals julie or jack and use the match
  • otherwise, it must be either john or an unfilled space so use that.
String[] merged = IntStream.range(0, arr1.length)
        .mapToObj(i->
                arr1[i].equals("julie") ? "julie" :
                arr2[i].equals("jack") ? "jack" : arr3[i])
        .toArray(String[]::new);

System.out.println(Arrays.toString(merged));

prints

[1, 2, julie, 4, john, 6, 7, 8, 9, john, 11, 12, julie, 14, jack, 16, 17, 18, 19
, john]

I think you may be able to do it straight from the data like so.

  • create a list of values and shuffle them. They could also be just random.
  • stream them and apply your criteria and return an array.
List<Integer> list = new ArrayList<>(IntStream.range(0, 21).boxed().toList());
Collections.shuffle(list);
System.out.println(list);

String[] result = list.stream()
        .map(i -> Integer.toString(i).contains("3") ?
                "julie" : i % 15 == 0 ? "jack" :
                i % 5 == 0 ? "john" : i + "")
        .toArray(String[]::new);
            
System.out.println(Arrays.toString(result));

Prints the source data and the result

[17, 9, 13, 8, 16, 19, 0, 6, 3, 1, 7, 2, 11, 4, 15, 20, 12, 18, 14, 5, 10]

[17, 9, julie, 8, 16, 19, jack, 6, julie, 1, 7, 2, 11, 4, jack, john, 12, 18, 14
, john, john]

Note: Based on your updated answer I tested in the order provided in 1,2,and 3. Anything divisible by 15 will be divisible by 5. This is also true for 30 which contains '3' and is divisible by 5 and 15. So the order in which one checks is important.

Upvotes: 2

gunescelil
gunescelil

Reputation: 313

How about this:

public void solution() {
        Integer[] integers = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
        List<String> numbers = Stream.of(integers).map(this::yourMappingFunction).collect(Collectors.toList());
        LOG.info("numbers: {}", numbers);
        // prints [1, 2, julie, 4, john, 6, 7, 8, 9, john, 11, 12, julie, 14, john, 16, 17, 18, 19, john]
    }

    // in the same class
    public String yourMappingFunction(Integer integer) {
        // write needed if conditions here and return the needed string for each
        // condition
        if (integer.toString().contains("3")) {
            return "julie";
        } else if (integer % 5 == 0) {
            return "john";
        } else if (integer % 15 == 0) {
            return "jack";
        } else {
            return integer.toString();
        }
    }

Upvotes: 0

besjon_c
besjon_c

Reputation: 172

Edit 1: I am not sure what you mean with:

merge all of them into each other and duplicate values should not be deleted to have below list

I am assuming you mean to return a list whose values are present in all three lists (common elements shared by all lists) which also includes the duplicate values inside respective lists.

Maybe you can find the intersection between 3 lists (finding common elements among them) and then append the duplicates value from each list - However, one can think of a case where all the lists contain same duplicate values e.g list1 = [1 1], list2 = [1 1] and list3 = [1 1]. How many 1s do you want on your final result?)

    // merge lists together - only common elements
    List<String> intersect = list1
        .stream()
        .filter(list2::contains)
        .filter(list3::contains)
        .collect(Collectors.toList());
    
    // iterate through your lists
    List<List<String>> listAll = Arrays.asList(list1, list2, list3);
    for (List<String> list: listAll) {
        // find duplicates inside each the list
        Set<String> items = new HashSet<>();
        List<String> duplicateValue = list
           .stream()
           .filter(n -> !items.add(n))
           .collect(Collectors.toList());
        // add to the duplicate to the final result
        intersect.addAll(duplicateValue);
        intersect.addAll(duplicateValue);
    }
    

Output: [1, 4, 7, 8, 11, julie, julie, john, john, jack, jack] where 1, 4, 7, 8, 11 are common on all lists, while the names are duplicates in respective single list


However, if you just want to merge all values of the lists together, there are a couple of ways you can do that:

Use Stream (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html) to combine the lists. Create a stream with lists and then flatten it to retrieve all elements

List<String> uniqueList = Stream.of(list1, list2, list3)
    .flatMap(Collection::stream).collect(Collectors.toList());

or

List<String> uniqueList = new ArrayList<>();
Stream.of(list1, list2, list3).forEach(joinedList::addAll);

See this related question for more details: Combine multiple lists in Java

Upvotes: 1

Alexander Ivanchenko
Alexander Ivanchenko

Reputation: 28988

I want to merge all of them into each other and duplicate values should not be deleted

If you want to preserve only duplicates and each element should appear only once in the resulting list, you can create an intermediate map Map<String, Boolean>, that would associate each unique string with a boolean value denoting whether it is a duplicate or not.

Then create a stream over the set of map entries, filter out the duplicates and collect the remained keys into a list.

List<String> result = Stream.of(collect1, collect2, collect3)
    .flatMap(List::stream)
    .collect(Collectors.toMap(
        Function.identity(),
        str -> false,         // first occurence - key isn't proved to be a duplicate
        (left, right) -> true // is a duplicate
    ))
    .entrySet().stream()
    .filter(Map.Entry::getValue)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

Upvotes: 0

Related Questions