0

How do I do it in a better way? I prefer java8 syntax.

These boolean conditions could grow.

boolean imageType = filetype.startsWith("image");

boolean videoType = filetype.startsWith("video");

boolean archiveType = filetype.contains("archive");

boolean jarType = filetype.contains("java-archive");

boolean audioType = filetype.startsWith("audio");

boolean zipType = filetype.contains("zip");

boolean xTarType = filetype.contains("x-tar");

boolean rarType = filetype.contains("rar");

if(!(imageType || videoType || archiveType || jarType || audioType || zipType || xTarType)) {
         //doSomething         
}
  • 1
    If you want to check 7 things there's no way to avoid running these checks. Especially since you're checking different strings. – Nir Alfasi Sep 07 '18 at 21:12
  • Are you using these Booleans outside of that if statement? If not you could consolidate them into 1 Boolean. – Matthew Sep 07 '18 at 21:13
  • 5
    This seems a bit like an X-Y question. The original code in itself with `String1`...`StringN` (and `String6` appearing twice) doesn't frankly make much sense. What is the actual problem you're trying to solve? – Mick Mnemonic Sep 07 '18 at 21:30

3 Answers3

1

A more object oriented approach could also be used to give you a little bit more information about the file type. I can imagine it being useful later on in your program.

You could do something like declare all your file types in an Enum:

public enum FileType {
    IMAGE("a"),
    VIDEO("b"),
    ARCHIVE("c"),
    JAR("d"),
    AUDIO("e"),
    ZIP("f"),
    XTAR("g");

    private String str;

    FileType(String str) {
        this.str = str;
    }

    public String getStr() {
        return str;
    }

    public static FileType getFileTypeForStr(String str) {
        for (FileType fileType : FileType.values()) {
            if (fileType.getStr().equalsIgnoreCase(str)) {
                return fileType;
            }
        }

        return null;
    }
}

Then, in your function, you could replace all your Booleans with a check to see if your input String1 is an included file type:

FileType fileType = FileType.getFileTypeForStr(String1); //And String2, String3, String4...
if (fileType != null) {
    System.out.printf("File type found of type %s", fileType.name());
} else {
    System.out.printf("No file type found for input %s", String1);
}

Since you have 7 different Strings to check, you could add a simple check to see if all the String1 variables are a match:

boolean isNotFileType = Stream
    .of(String1, String2, String3, String4, String5, String6, String7)
    .map(FileType::getFileTypeForStr)
    .anyMatch(Objects::isNull);
nbokmans
  • 5,492
  • 4
  • 35
  • 59
0

1) Regroup your conditions in Predicates. Take the case of an Enum:

public enum PredicateEnum {

    IMAGE   (filetype -> filetype.startsWith("image")),
    VIDEO   (filetype -> filetype.startsWith("video")),
    ARCHIVE (filetype -> filetype.contains("archive")),
    JAR     (filetype -> filetype.contains("java-archive")),
    AUDIO   (filetype -> filetype.startsWith("audio")),
    ZIP     (filetype -> filetype.contains("zip")),
    X_TAR   (filetype -> filetype.contains("x-tar")),
    RAR     (filetype -> filetype.contains("rar"));

    private Predicate<String> predicate;

    PredicateEnum(Predicate<String> predicate) {
        this.predicate = predicate;
    }

    public Predicate<String> getPredicate() {
        return predicate;
    }
}

2) Use Stream#reduce and Predicate#or to create a single Predicate which is the result of all your predicates connected by logic OR operators:

Predicate<String> predicateOr = Stream.of(PredicateEnum.values())
        .map(PredicateEnum::getPredicate)
        .reduce(Predicate::or)
        .orElse(s -> false);

System.out.println("image.png: "      + predicateOr.test("image.png"));
System.out.println("my-archive.txt: " + predicateOr.test("my-archive.txt"));
System.out.println("foo : "           + predicateOr.test("foo"));

3) Use the result of Predicate#test in your if statement. For example, the code above prints out:

image.png: true
my-archive.txt: true
foo : false
Gustavo Passini
  • 2,348
  • 19
  • 25
0

Here are a couple of ways to make this more "scaleable".

  1. Use a regex:

    Pattern p = Pattern.compile("^video|^audio|^image|zip|rar|java-archive|x-tar");
    if (!p.matcher(filetype).find()) {
        // do stuff
    }
    
  2. Use arrays or lists. For example:

    String[] prefixes = new String[]{"video", "audio", "images"};
    String[] contains = new String[]{"zip", "rar", "x-tar", "jar-archive"};
    boolean match = false;
    for (String p : prefixes) {
        if (filetype.startsWith(p)) {
            match = true;
        }
    }
    ...
    if (!match) {
        // do stuff
    }
    

Clearly, the regex approach is more concise, but the array approach is probably more efficient (if that matters!). It depends on how the regex engine copes with a regex with lots of alternatives.

Both approaches will scale; e.g by updating the regex, or by adding strings to the arrays.

In both cases, you could easily load the relevant criteria from a properties file or similar ... and avoid making code changes.

I'm not convinced the Java 8 lambdas and streams are a good fit for this problem.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216