0

I have a code which prints the creation date of sub directories. I am getting my expected output but the way I have written my code is not good and I think it can be optimized in a much better way. As you can see, there are three lines of code inside for loop which gets executed every time for loop runs which increases the complexity.

public static void main(String aa[]) throws IOException
{
        DateFormat simpleDateFormat = new SimpleDateFormat("MM-dd-yyyy");

        File file = new File("G:\\TestFiles");
        File[] files = file.listFiles();

        for(File subDir: files)
        {

        BasicFileAttributes attribute = Files.readAttributes(subDir.toPath(), BasicFileAttributes.class);

        FileTime filetime = attribute.creationTime();

        String strDate = simpleDateFormat.format(filetime.toMillis());

        System.out.println(strDate);

        }       

}

I am trying to write my code in such a way that inside for loop I should only have print statement and the remaining three lines should be outside my for loop. One approach I came was to declare Path of my sub folders but then it didn't gave the correct creation date of my sub folders.

7
  • Your implementation seems right to me. Why do you want to move the remaining 3 lines outside your for loop? They are different for every file. And you need to get their value for each file. Commented Jul 25, 2015 at 1:37
  • 1
    You're not using subDir anywhere within the for loop, so the whole loop seems redundant to me. Should it be BasicFileAttributes attribute = Files.readAttributes(subDir.toPath(), BasicFileAttributes.class); instead? Commented Jul 25, 2015 at 1:38
  • @Rubel Please fix your code per the comment by Mic Mnemonic. You can edit your Question -- look for an "Edit" link below your question's tags (if using a web browser). Commented Jul 25, 2015 at 4:59
  • @Rubel Please explain what you meant by "remaining lines should be outside my for loop". Did you mean the BasicFileAttribute, FileTime, and String, lines? Why do you perceive the need to move them outside the loop? And what did you mean by "optimized in a much better way", less lines of code, better readability, better runtime performance (speed)? Commented Jul 25, 2015 at 5:01
  • @BasilBourque Yes, everytime the loop iterates, the BasicFileAttribute, FileTime, and String lines are also executed. So, I thought instead of running the 3 lines of codes inside the for loop, why not keep them outside and make use of them only once. Regarding optimizing, yes I mean speed and performance. Right now my directory ("G:\\TestFiles") has only 5 folders but if the number of folders are huge in the directory then for loop will iterate those 3 lines every time it reads a folder. I hope I was able to explain my point. Commented Jul 25, 2015 at 5:28

2 Answers 2

3

It looks fine for me...you can strip it down to:

    final DateFormat simpleDateFormat = new SimpleDateFormat("MM-dd-yyyy");
    final File file = new File("G:\\TestFiles");

    for (File subDir : file.listFiles()) {
      System.out.println(simpleDateFormat.format(Files.readAttributes(file.toPath(), BasicFileAttributes.class)
          .creationTime().toMillis())
      );
    }

...but keep an eye on file.listFiles() since you might get easily a NPE (though you are not checking for it in the original code also).

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Please mark the answer as useful as I am new to stackoverflow and I do not have enough reputation.
2

Optimizing

Your question is not clear about what you meant by optimizing.

Moving Lines Outside Loop

The lines of code that execute within the for loop need to run inside the loop. There is nothing unoptimized about that. I do not see anything in your code that can be moved outside the loop.

If you are worried about creating objects that will almost immediately be destroyed and become "garbage" for the JVM’s garbage collector… stop worrying. The modern JVMs are extremely well-honed and optimized for such short-lived objects. Don't create such objects frivolously in a long-running loop (hundreds of thousands or millions of iterations), but also don't fret about it.

In the same vein, see my code example below. Notice how I put the time zone, locale, and formatter before the loop. Those lines would work just as well inside the for loop, but they would be executing repeatedly and creating new instances with no benefit. Those three particular objects are built to be reused, so I moved them up top. When drafting code I might well have them in the loop, and later identify them as qualified for being moved out of the loop.

Fewer Lines

If by optimizing you meant reducing the number of lines for the sake of shorter code, I strongly recommend against that for three reasons.

  • Readability of code is much more important than line count. Programmers need to be able easily read and make sense of code rather than decipher it.
  • Debugging is much easier if you have simple short lines of code. By "short" I mean focused on one (or few) specific operation being accomplished (not actual line length). If too many nested operations occur within a line, then tracking values and effects when debugging becomes more complicated.
  • The modern JVM technology such as Oracle’s HotSpot & JRockit do amazing things with optimizing code both during compilation and during runtime. Those optimizations are made most powerful when given relatively simple straightforward lines of code. Making code overly dense or "clever" can actual reduce opportunities for Java compiler/runtime optimization.

java.time

One big improvement you could make is to avoid the use of the java.util.Date/.Calendar & SimpleTextFormat classes. Those old classes are notoriously troublesome, flawed in both design and implementation.

Those classes have been supplanted in Java 8 and later by the new java.time package. This new date-time framework is inspired by the Joda-Time library, defined by JSR 310, and extended by the ThreeTen-Extra project.

That FileTime class you use is java.time-savvy. Note the toInstant method.

Assign the desired/expected time zone (ZoneId) to that Instant. If you do not specify a time zone, the JVM’s default time zone is implicitly applied – generally the better practice is to specify rather then rely implicitly on a default. Beware that the JVM’s current default time zone can be changed at runtime in any moment by any code in any thread of any app running within that JVM.

Create a String representation in a Locale-appropriate manner.

Let's imagine a Québécois manager looking at data pertaining to business operations in India. We want to show the date-time values formatted to her customs but framed in the time zone of India. Time zone is crucial in determining the date (a new day dawns earlier in India than in Canada).

final ZoneId zoneKolkata = ZoneId.of( "Asia/Kolkata" );  // Adjust the date-time value as it would appear in India. Or, ZoneId.systemDefault()
final Locale localeQuébécois = Locale.CANADA_FRENCH;  // Or Locale.getDefault()
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( localeQuébécois ).withZone( zoneKolkata );

final File startingFile = new File( "/Users/brainydeveloper/Downloads" );  // "G:\\TestFiles"
for ( File file : startingFile.listFiles( ) ) {

    BasicFileAttributes attribute = null;
    try {
        attribute = Files.readAttributes( file.toPath( ), BasicFileAttributes.class );
    } catch ( IOException e ) {
        e.printStackTrace( );  // Add your own smart exception handling.
    }

    FileTime fileTime = attribute.creationTime( );
    String output = formatter.format( fileTime.toInstant( ) );
    System.out.println( output );
}

Example output.

2014-04-19
2010-10-12
2015-06-21

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.