Indi
Indi

Reputation: 429

How to java Program to Check if an array contains a given two different values?

I want to write a code to check the existence of given two values in a List.

List<Tag> tags = new ArrayList<>();

The requirement is to return true only if the List tag contains both "start" and "end" values. My code is like this, but it doesn't cater to the requirement.

public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
        boolean isSuccess = false;
        int count = 0;
        for (Tag tag : tags) {
            if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
                count++;
                if (count == 2)
                    break;
                isSuccess = true;
            }

        }
        return isSuccess;

Can someone help me with to resolve this issue?

Upvotes: 1

Views: 1106

Answers (4)

daniu
daniu

Reputation: 15028

You could also use

tags.stream()
    .map(Tag::getKey)
    .distinct()
    .filter(t -> "start".equals(t) || "end".equals(t))
    .count() == 2;

This would also fix the issue that your original code falsely returns true if the list contains statt or end twice.

Upvotes: 2

G.B.
G.B.

Reputation: 11

What about

tags.containsAll(Arrays.asList(new Tag("start"), new Tag("stop")))

Upvotes: -2

MadProgrammer
MadProgrammer

Reputation: 347332

This...

if (count == 2)
  break;
isSuccess = true;

doesn't make sense. This will set isSuccess even if there is only one match

The long winded approach

Okay, let's assuming for a second that you only care if there is at least one start and one end (discounting duplicates). One approach would be to use to state flags, one for start and one for end. To keep it simple, they would start of as 0 but would only ever be a maximum of 1 (because we don't want duplicates), then you might be able to do something like...

public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
    boolean isSuccess = false;
    int starts = 0;
    int ends = 0;
    for (Tag tag : tags) {
        if (tag.getKey().equals("start")) {
            starts = 1;
        } else if (tag.getKey().equals("end")) {
            ends = 1;
        }
    }
    isSuccess = (starts + ends) == 2;
    return isSuccess;
}

Ok, you don't need isSuccess = (starts + ends) == 2; and could simply return the result of the comparison. You could also break out of the loop if (starts + ends) == 2 and save yourself from unnecessary computation

for (Tag tag : tags) {
    if (tag.getKey().equals("start")) {
        starts = 1;
    } else if (tag.getKey().equals("end")) {
        ends = 1;
    }

    if ((starts + ends) == 2) {
        break;
    }
}

Using streams...

One approach might be to make use the streams support and simply filter the List and count the results, for example...

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        List<Tag> tags = new ArrayList<Tag>(25);
        tags.add(new Tag("begin"));
        tags.add(new Tag("front"));
        tags.add(new Tag("start"));
        tags.add(new Tag("finish"));
        tags.add(new Tag("tail"));
        tags.add(new Tag("end"));

        boolean isSuccessful = tags.stream().filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end")).count() >= 2;
        System.out.println(isSuccessful);
    }

    public class Tag {
        private String key;

        public Tag(String key) {
            this.key = key;
        }

        public String getKey() {
            return key;
        }


    }
}

Updated...

Okay, this got complicated fast. Let's assume you don't want to match two start tags, so you MUST have both one end and one start tag

So, using the above, example, we can modify the Tag class to support equals (and by extension hashcode)

public class Tag {

    private String key;

    public Tag(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    @Override
    public String toString() {
        return getKey();
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 73 * hash + Objects.hashCode(this.key);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Tag other = (Tag) obj;
        if (!Objects.equals(this.key, other.key)) {
            return false;
        }
        return true;
    }

}

Then we can simply use distinct to filter out any duplicates, for example...

boolean isSuccessful = tags
        .stream()
        .distinct()
        .filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end"))
        .count() >= 2;

Probably not the most efficient solution, but certainly one of the shortest

Upvotes: 3

Scary Wombat
Scary Wombat

Reputation: 44854

In this code

if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
     count++;
     if (count == 2)
            break;
     isSuccess = true;
}

you are setting isSuccess to true whenever the tag is start or end.

Better way would be

if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
    count++;
    if (count == 2)
        return true;
}

Upvotes: 2

Related Questions