简体   繁体   中英

Find sub collection not adjacent but in the same order in java

How can I find in Java (8) if a collection (list or set) is subset of another collection although the elements are no adjacent for example [1,2,3,4,5] as the large collection and if I want to search for [2,3,4] return true, also [2,5] return true BUT [4,2] return false although 4 and 2 are in the collection but are not in the same order

Is there a utility help me to do this? Or a piece of code doing this properly?

Thanks

Not fully tested, but you can try something like this,

    int[] x = {1,2,3,4,5};
    int[] y = {2,5};
    int yIndex = 0;

    for(int i: x){
        if(y[yIndex] == i){
            yIndex++;
            if(yIndex >= y.length){
                break;
            }
        }
    }

    System.out.println(yIndex == y.length ? "Match" : "Not Match");

You can easily use one utility method provided by Collections that does exactly what you intend to do.

    Collections.disjoint(c1, c2)

The above method returns true if the two collection passed does not have any item in common and the other way around. Exactly the thing you want.

This function returns true if a contains b.

This function converts collection to array, if your collection class not implements .toArray() function it won't work!

public class CollectionUtils {
    private CollectionUtils() {
    }

    /**
     * @return true if A contains B in order
     */
    public static <T> boolean checkAcontainsB(Collection<T> a, Collection<T> b) {
        if (a == null || b == null || b.size()>a.size()) {
            return false;
        }
        if (b.isEmpty()) {
            return true;
        }
        final Object[] aElements = a.toArray();
        final Object[] bElements = b.toArray();

        for (int i = 0; i < aElements.length; i++) {

            int bIndex = 0;
            for(int j = i; j< aElements.length; j++) {
                if(aElements[j] == bElements[bIndex]) {
                    bIndex++;
                    if(bIndex>=bElements.length) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

}

you can test it:

@Test
public void test() {
    Assert.assertFalse(CollectionUtils.contains(Arrays.asList(1,2,3,4), Arrays.asList(2,3,4,5)));
    Assert.assertTrue(CollectionUtils.contains(Arrays.asList(1,2,3,4), Arrays.asList(2,3,4)));
    Assert.assertTrue(CollectionUtils.contains(Arrays.asList(1,2,3,4), Arrays.asList(2,4)));
    Assert.assertTrue(CollectionUtils.contains(Arrays.asList(1,2,3,4,1,2,3,4), Arrays.asList(3,4,2)));
    Assert.assertFalse(CollectionUtils.contains(Arrays.asList(1,2,3,4), Arrays.asList(2,3,4,5,6)));
}

I don't know of any generic solution for your problem, but below you could find an custom-made solution for your problem.

public static boolean containsArray(int[] a, int[] s) {
    if (a == null || s == null) return false;
    if (a.length < s.length) return false;

    int i = -1;
    for (int current : s) {
        do {
            i++;
            if (i == a.length) {
                return false;
            }
        } while (a[i] != current);
    }

    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM