2

I have an arrayList of list of String

ArrayList<List<String>> temp = new ArrayList<List<String>>();

Now, imagine we have 3 list o more like :

  • list 1 : [3,8,15,98]
  • list 2 : [3,4,21,98]
  • list 3 : [5,4,76,90]

I would like to print only the smallest list. I mean the list which has the smallest ascending order. For example, if we take the three list abose :

  • at index 0 :

item of list 1 & 2 = 3

item of list 3 = 5

3<5 so i will not print list 3

  • at index 1 :

item of list1 = 8

item of list 2 = 4

4<8 so I have to print list 2

Indeed, I try to compare the items of each list at each index.

    ArrayList<List<String>> temp = new ArrayList<List<String>>();
//...
//...
        for(int i=0; i<temp.size()-1; i++) {
            for(int j=0; j<temp.get(i).size(); j++) {
                
                
                int min = Integer.valueOf(temp.get(i+1).get(j));
                if(Integer.valueOf(temp.get(i).get(j)) < min) {
                    min = Integer.valueOf(temp.get(i).get(j));
                }else if(Integer.valueOf(temp.get(i).get(j)) >=min) {
                    temp.get(i).remove(j);
                }
            }

But the method seem not be the best way. Do you have some idea ? THK

Community
  • 1
  • 1
Bigote
  • 95
  • 7
  • What happens if one list has a smaller size than the others? Basically get the number of lists, for each list get the index i and compare it, then get index i + 1. No need for many loops. Index access for all lists is sufficient. – peterulb Aug 28 '19 at 11:25
  • Normally, all my lists must be the same size – Bigote Aug 28 '19 at 11:29

3 Answers3

1

Any comparison algorithm can easily be written using Java Comparators. But first lets assume that you are comparing a list of Integers and not the list of Strings, because that's what you are doing. If your original data is presented in the format of Strings then obviously you must convert the data into numeric type, to compare those as numbers.

You can have a TreeSet, which can preserve the ordering of it's elements, by using your custom comparison algorithm.

You can write a Comparator which can compare by multiple object properties. This is useful , when Lets say you want to compare the list of employees by first name and than by second name (by column1 and after that by column2). In our case we can compare by first index, after that, compare by second index, and then by third, and this chain can go on as deeply into your lists as you need.

public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(3,8,15,98);
        List<Integer> list2 = Arrays.asList(3,4,21,98);
        List<Integer> list3 = Arrays.asList(5,4,76,90);

        int comparisonLength = 4;

        Comparator<List<Integer>> comparator = Comparator.comparing(list -> list.get(0));
        for(int i = 1; i< comparisonLength; i++) {
            final int comparedIndex = i;
            comparator = comparator.thenComparing(list -> list.get(comparedIndex));
        }

        TreeSet<List<Integer>> treeSet = new TreeSet<>(comparator);

        treeSet.add(list1);
        treeSet.add(list2);
        treeSet.add(list3);

        System.out.println(treeSet.iterator().next()); //prints the first element in the collection
    }
Mikhail Valiev
  • 113
  • 1
  • 11
  • 1
    This does not work as expected. it prints [3,4,21,98] but should print [3,4,15,90] – Stephan Hogenboom Aug 28 '19 at 11:36
  • From what I read - the author is comparing the Lists and not the elements inside of those lists, so I assume the output is the one of the original lists and not a completely new list? there is no such list as [3,4,15,90] among the input – Mikhail Valiev Aug 28 '19 at 11:43
  • In my example, list 1 & list 2 start with 3, so to print list 2, I should to compare the following elements. – Bigote Aug 28 '19 at 11:49
  • I think the code in my answer does exactly what you want? – Mikhail Valiev Aug 28 '19 at 11:52
  • @MikhailValiev hello again! I have a last question to complete your answer. In my case, all my list are stored in temp : `ArrayList> temp = new ArrayList>();` ... Indeed, in my case, i didn't precise here, but all my list are created by a loop. So inside your **for loop**, how can I replace `comparator = comparator.thenComparing(list -> list.get(comparedIndex));` to compare all my list which are inside **temp** ? – Bigote Aug 28 '19 at 17:31
  • 1
    The comparator is used by TreeSet, a collection, which implements SortedSet interface. In my example, whenever you add an element into TreeSet> the inner code of TreeSet preserves the iteration order, by applying our comparator to those elements. Comparator and TreeSet remains the same, but you need to know the length of an array to define "comparisonLength" variable, convert your List objects into List objects and put them into TreeSet. You can put them all at once by using addAll() method. – Mikhail Valiev Aug 28 '19 at 17:44
  • `for(List list : temp) treeSet.add(list); System.out.println(treeSet.iterator().next());` ..... gives this error **java.util.NoSuchElementException**..... apparently `treeSet.iterator().next()` is the problem ... – Bigote Aug 29 '19 at 08:45
  • treeSet.iterator().next() was a quick way to get the first element in the collection. If it gives you an exception, that means there is no elements in the collection. Are you sure you are doing it right? You really should read at least some basic tutorial about Java Collections and how Iterator works. – Mikhail Valiev Aug 29 '19 at 08:50
  • Yes, now I understand why! You're right, i need to read more aout it. Thk a lot ! – Bigote Aug 29 '19 at 09:10
1

Here's another approach, using Java Streams:

List<Integer> list1 = Arrays.asList(3, 8, 15, 98);
List<Integer> list2 = Arrays.asList(3, 4, 21, 98);
List<Integer> list3 = Arrays.asList(5, 4, 76, 90);

Optional<List<Integer>> result = Stream.of(list1, list2, list3)
    .sorted((a, b) -> IntStream.range(0, a.size())
        .map(i -> Integer.compare(a.get(i), b.get(i)))
        .filter(i -> i != 0)
        .findFirst()
        .orElse(0))
    .findFirst();

System.out.println(result);

This is how it works.

We stream over the lists, sort the stream using a certain Comparator and then find the first occurrence. It returns an Optional, which is Optional.empty() in case you don't provide any list, so naturally there is no "smallest".

The sort function does the following. It walks over all indexes of the list, and compares the elements at that position within both lists with eachother. It keeps walking until the comparision returns a non-zero value. This means the elements at that position differ. If the comparisions for all positions return 0, then that means that there is no difference between the list (provided that all lists are equal of length).


If you want to handle lists unequal of length, you could rewrite the sort function accordingly. It walks over all indexes valid in both lists. If all elements are equal, then the shortest list is selected.

(a, b) -> IntStream.range(0, Math.min(a.size(), b.size()))
    .map(i -> Integer.compare(a.get(i), b.get(i)))
    .filter(i -> i != 0)
    .findFirst()
    .orElse(Integer.compare(a.size(), b.size()))

Ideone example.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
0
public static void main(String[] args) {
        List<String> l1 = Arrays.asList("3", "8", "15", "98");
        List<String> l2 = Arrays.asList("3", "4", "21", "98");
        List<String> l3 = Arrays.asList("5", "4", "76", "90");
        ArrayList<List<String>> list = (ArrayList<List<String>>) Stream.of(l1, l2, l3).collect(Collectors.toList());

        System.out.println(
                list.stream()
                .min(
                        (a, b) -> {
                            for (int i = 0; i < Math.min(a.size(), b.size()); i++) {
                                if (!a.get(i).equals(b.get(i))) {
                                    return Integer.parseInt(a.get(i)) - Integer.parseInt(b.get(i));
                                }
                            }
                            throw new RuntimeException();
                        }
                ).orElseThrow(RuntimeException::new)
        );
    }
Eduard Dubilyer
  • 991
  • 2
  • 10
  • 21