我有一个数组的文件,并想得到一个ArrayList,其中只包含音频文件从所说的阵列。
我想知道是否有一种方法可以提高我的代码的性能(现在迭代14000个文件需要大约85秒)。
我的代码:
final File[] ArrayOfFiles = mysteriousFunction(); //returns a ton of files
final MediaMetadataRetriever iLoveThisThing = new MediaMetadataRetriever();
ArrayList<File> audioFiles = new ArrayList<>();
for (File file : ArrayOfFiles)
{
final String fileString = file.toString();
String extension = "";
final int lastIndexOfDot = fileString.lastIndexOf('.');
final int lastIndexOfSeperator = fileString.lastIndexOf(File.separatorChar);
if (lastIndexOfDot > lastIndexOfSeperator)
{
extension = fileString.substring(lastIndexOfDot + 1);
}
switch (extension)
{
case "mp3":
case "mp4":
case "3gp":
case "m4a":
case "aac":
case "ogg":
case "wav":
case "mid":
case "ts":
case "imy":
case "flac":
case "xmf":
case "mxmf":
case "mkv":
iLoveThisThing.setDataSource(fileString);
final String foo1 = iLoveThisThing.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
if (foo1 != null)
{
String foo2 = foo1.substring(0, foo1.indexOf('/'));
if (foo2.equals("audio"))
{
audioFiles.add(file);
}
}
break;
default:
break;
}
}
我已经收到了相当多的技巧,所以这是我的更新代码:
private static final Set<String> extensions = new HashSet<>(Arrays.asList("mp3", "mp4", "3gp", "m4a", "aac", "ogg", "wav", "mid", "ts", "imy", "flac", "xmf", "mxmf", "mkv"));
public static void DoStuff()
{
new Thread(() -> {
final File[] allFiles = get_a_ton_of_files();
final Set<File> audioFilesSet = ConcurrentHashMap.newKeySet(allFiles.length);
Arrays.stream(allFiles).parallel().forEach(file -> {
final String fileString = file.toString();
final int lastIndexOfDot = fileString.lastIndexOf('.');
if (lastIndexOfDot > fileString.lastIndexOf(File.separatorChar))
{
final String extension = fileString.substring(lastIndexOfDot + 1);
if (extensions.contains(extension))
{
final MediaMetadataRetriever myMediadataRetriever = new MediaMetadataRetriever();
myMediadataRetriever.setDataSource(fileString);
final String mime = myMediadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
if (mime != null && mime.startsWith("audio"))
{
audioFiles.add(file);
}
myMediadataRetriever.release();
}
}
});
}).start();
}
任何进一步的优化显然仍然是高度赞赏的。
发布于 2018-05-31 00:00:38
你可以做一些事情来提高你的速度:
for (File file : ArrayOfFiles)
可以并行执行MediaMetadataRetriever
。这很耗时。在这个类中的其他方法之前调用这个方法。这种方法可能很耗时。
您可以改用ContentResolver
。
Uri uri = Uri.fromFile(file);
ContentResolver contentResolver = context.getContentResolver();
String mime = contentResolver.getType(uri);
把它付诸行动:
Set<File> audioFileSet = ConcurrentHashMap.newKeySet(ArrayOfFiles.length);
Set<String> ext = new HashSet<>(Arrays.asList("mp3", "mp4", ...));
ContentResolver contentResolver = context.getContentResolver();
Arrays.stream(ArrayOfFiles).parallel().forEach(file -> {
String extension = ...;
if (ext.contains(extension)) {
String mime = contentResolver.getType(Uri.fromFile(file));
...
audioFileSet.add(file);
}
});
// If you want list:
List<File> list = new ArrayList<>(audioFileSet);
如果使用MediaMetadataRetriever
Arrays.stream(ArrayOfFiles).parallel().forEach(file -> {
String extension = ...;
if (ext.contains(extension)) {
// Must init in side loop
MediaMetadataRetriever iLoveThisThing = new MediaMetadataRetriever();
iLoveThisThing.setDataSource(fileString);
String mime = iLoveThisThing.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
...
audioFileSet.add(file);
// Dont forget to release resource:
iLoveThisThing.release();
}
});
发布于 2018-05-30 23:36:36
最好使用以下方法检查文件是否为音频文件:
public static boolean isMediaFile(String filepath) {
String mimeType = URLConnection.guessContentTypeFromName(filepath);
return mimeType != null && mimeType.startsWith("audio");
}
因此您甚至不需要使用Switch-Case语句。试试看:
if (isMediaFile(file.getAbsolutePath()) {
audioFiles.add(file);
}
https://stackoverflow.com/questions/50608387
复制相似问题