Удаление дублирующихся строк в файле с помощью Java

Редактировать 15 июня 2016 г.

Я не уверен, к какой версии добавлена ​​библиотека поддержки , но похоже, что эта функциональность теперь встроена. Просто используйте:

NotificationManagerCompat.getEnabledListenerPackages(context); ( ссылка на документы )

Возвращает Set, через который вы можете выполнить итерацию, чтобы найти имя вашего пакета. Обратите внимание, что я лично не проверял это. Но похоже, что это предпочтительнее использовать вместо моего старого решения ниже.


Старое решение

Этот код работает для моего приложения:

ContentResolver contentResolver = context.getContentResolver();
String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
String packageName = context.getPackageName();

// check to see if the enabledNotificationListeners String contains our package name
if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName))
{
    // in this situation we know that the user has not granted the app the Notification access permission
    throw new Exception();
}
else
{
    doSomethingThatRequiresNotificationAccessPermission();
}

Типичные значения, которые я видел для enabledNotificationsListeners String, выглядят так:

  • Пользователь не предоставил ни одно из своих приложений Разрешение на доступ к уведомлению
    • null или ""
  • Пользователь дал одно уведомление приложения разрешение доступа
    • "com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"
  • Пользователь дал два приложения Разрешение на доступ к уведомлению
    • "com.scootrnova.android/com.scootrnova.android.ListenerService:com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"

Эта реализация очень проста и прекрасно работает:)

PS Я получил идею использовать жестко закодированную строку "enabled_notification_listeners" из этого ответа .

25
задан Peter Lawrey 10 April 2016 в 13:51
поделиться

12 ответов

Hmm... 40 megs seems small enough that you could build a Set of the lines and then print them all back out. This would be way, way faster than doing O(n2) I/O work.

It would be something like this (ignoring exceptions):

public void stripDuplicatesFromFile(String filename) {
    BufferedReader reader = new BufferedReader(new FileReader(filename));
    Set<String> lines = new HashSet<String>(10000); // maybe should be bigger
    String line;
    while ((line = reader.readLine()) != null) {
        lines.add(line);
    }
    reader.close();
    BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
    for (String unique : lines) {
        writer.write(unique);
        writer.newLine();
    }
    writer.close();
}

If the order is important, you could use a LinkedHashSet instead of a HashSet. Since the elements are stored by reference, the overhead of an extra linked list should be insignificant compared to the actual amount of data.

Edit: As Workshop Alex pointed out, if you don't mind making a temporary file, you can simply print out the lines as you read them. This allows you to use a simple HashSet instead of LinkedHashSet. But I doubt you'd notice the difference on an I/O bound operation like this one.

37
ответ дан 28 November 2019 в 17:58
поделиться

There are two scalable solutions, where by scalable I mean disk and not memory based, depending whether the procedure should be stable or not, where by stable I mean that the order after removing duplicates is the same. if scalability isn't an issue, then simply use memory for the same sort of method.

For the non stable solution, first sort the file on the disk. This is done by splitting the file into smaller files, sorting the smaller chunks in memory, and then merging the files in sorted order, where the merge ignores duplicates.

The merge itself can be done using almost no memory, by comparing only the current line in each file, since the next line is guaranteed to be greater.

The stable solution is slightly trickier. First, sort the file in chunks as before, but indicate in each line the original line number. Then, during the "merge" don't bother storing the result, just the line numbers to be deleted.

Then copy the original file line by line, ignoring the line numbers you have stored above.

0
ответ дан 28 November 2019 в 17:58
поделиться

Does it matter in which order the lines come, and how many duplicates are you counting on seeing?

If not, and if you're counting on a lot of dupes (i.e. a lot more reading than writing) I'd also think about parallelizing the hashset solution, with the hashset as a shared resource.

0
ответ дан 28 November 2019 в 17:58
поделиться

The Hash Set approach is OK, but you can tweak it to not have to store all the Strings in memory, but a logical pointer to the location in the file so you can go back to read the actual value only in case you need it.

Another creative approach is to append to each line the number of the line, then sort all the lines, remove the duplicates (ignoring the last token that should be the number), and then sort again the file by the last token and striping it out in the output.

1
ответ дан 28 November 2019 в 17:58
поделиться
  • Read in the file, storing the line number and the line: O(n)
  • Sort it into alphabetical order: O(n log n)
  • Remove duplicates: O(n)
  • Sort it into its original line number order: O(n log n)
2
ответ дан 28 November 2019 в 17:58
поделиться

If you could use UNIX shell commands you could do something like the following:

for(i = line 0 to end)
{
    sed 's/\$i//2g' ; deletes all repeats
}

This would iterate through your whole file and only pass each unique occurrence once per sed call. This way you're not doing a bunch of searches you've done before.

0
ответ дан 28 November 2019 в 17:58
поделиться

If the order does not matter, the simplest way is shell scripting:

<infile sort | uniq > outfile
3
ответ дан 28 November 2019 в 17:58
поделиться

You could use Set in the Collections library to store unique, seen values as you read the file.

Set<String> uniqueStrings = new HashSet<String>();

// read your file, looping on newline, putting each line into variable 'thisLine'

    uniqueStrings.add(thisLine);

// finish read

for (String uniqueString:uniqueStrings) {
  // do your processing for each unique String
  // i.e. System.out.println(uniqueString);
}
3
ответ дан 28 November 2019 в 17:58
поделиться

Возможно, что-то вроде этого:

BufferedReader in = ...;
Set<String> lines = new LinkedHashSet();
for (String line; (line = in.readLine()) != null;)
    lines.add(line); // does nothing if duplicate is already added
PrintWriter out = ...;
for (String line : lines)
    out.println(line);

LinkedHashSet сохраняет порядок вставки, в отличие от HashSet , который (хотя и немного быстрее для поиска / вставки) будет изменить порядок всех строк.

4
ответ дан 28 November 2019 в 17:58
поделиться

Аналогичный подход

public void stripDuplicatesFromFile(String filename) {
    IOUtils.writeLines(
        new LinkedHashSet<String>(IOUtils.readLines(new FileInputStream(filename)),
        "\n", new FileOutputStream(filename + ".uniq"));
}
10
ответ дан 28 November 2019 в 17:58
поделиться

Try a simple HashSet that stores the lines you have already read. Then iterate over the file. If you come across duplicates they are simply ignored (as a Set can only contain every element once).

2
ответ дан 28 November 2019 в 17:58
поделиться

Хорошо, большинство ответов немного глупые и медленные поскольку он включает добавление строк в какой-то хэш-набор или что-то еще, а затем снова перемещение его из этого набора. Позвольте мне показать наиболее оптимальное решение в псевдокоде:

Create a hashset for just strings.
Open the input file.
Open the output file.
while not EOF(input)
  Read Line.
  If not(Line in hashSet)
    Add Line to hashset.
    Write Line to output.
  End If.
End While.
Free hashset.
Close input.
Close output.

Пожалуйста, ребята, не усложняйте его больше, чем нужно. :-) Не беспокойтесь о сортировке, вам не нужно.

15
ответ дан 28 November 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: