Reputation: 262
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.
Upvotes: 0
Views: 227
Reputation: 338506
Your question is not clear about what you meant by optimizing.
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.
If by optimizing you meant reducing the number of lines for the sake of shorter code, I strongly recommend against that for three reasons.
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
Upvotes: 2
Reputation:
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).
Upvotes: 3