问题
From following list I need only 'wow' and 'quit'.
List<String> list = new ArrayList();
list.add("test");
list.add("test");
list.add("wow");
list.add("quit");
list.add("tree");
list.add("tree");
回答1:
you can check the frequency of an element in the Collection and rule out the elements which have frequency higher than 1.
List<String> list = new ArrayList<String>();
list.add("test");
list.add("test");
list.add("wow");
list.add("quit");
list.add("tree");
list.add("tree");
for(String s: list){
if(Collections.frequency(list, s) == 1){
System.out.println(s);
}
Output:
wow
quit
回答2:
This snippet should leave you with a set (output
) which contains only non-duplicated elements of your list.
HashSet<String> temp = new HashSet<String>();
HashSet<String> output = new HashSet<String>();
for (String element : list)
{
if (temp.contains(element)) output.remove(element);
else
{
temp.insert(element);
output.insert(element);
}
}
Operates in O(n*log(n)) time: one set of logarithmic operations (set lookups, inserts, etc) for each of the n elements in the list.
回答3:
You can use HashMap impl to count occurences and select only onces that occur once.
e.g.
void check(List<String> list)
{
Map<String,Integer> checker = new HashMap<String,Integer>();
List<String> result = new ArrayList<String>();
for(String value: list)
{
Integer count = checker.get(value);
if (count==null)
{
count = 0;
}
checker.put(value, ++count);
}
// now select only values with count == 1
for(String value: checker.keySet())
{
if (checker.get(value) == 1)
{
result.add(value);
}
}
System.out.println(result);
}
回答4:
And a Third way
List result = new ArrayList();
for(Object o : list){
if(list.indexOf(o) == list.lastIndexOf(o))
result.add(o);
}
回答5:
@ROMANIA_Engineer's solution should work just fine, but it does hide an O(n2) complexity in it, since Collections.frequency
is an O(n) operation.
A more efficient solution that can still be squeezed in to a single statement could be to count how many times each item occurs and filter just items that appear once:
list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1L)
.map(Map.Entry::getKey)
.forEach(System.out::println);
回答6:
Java 8+
list.stream() // Stream
.filter(i -> Collections.frequency(list, i) == 1) // Stream
.collect(Collectors.toList()) // List
.forEach(System.out::println); // void
It prints every element from that list that appears exactly once.
Details:
- lambda expressions
- Stream interface
- Collections class
回答7:
Here is a Java 8 way without streams:
Map<String, Long> counts = new HashMap<>();
list.forEach(word -> counts.merge(word, 1L, Long::sum));
counts.values().removeIf(count -> count > 1);
This first iterates the list and stores the frequency of each word in the counts
map. For this I'm using the Map.merge method, which either associates the provided value (1L
in this case) with the given key (word
here) or uses the provided merge function (Long::sum
) to combine an existent value with the given one.
Then, words with a frequency greater than 1
are removed from the map via the Collection.removeIf method.
The whole process has O(n)
time complexity.
回答8:
If you're open to using a third-party library, the following can be used with Eclipse Collections:
List<String> list = Arrays.asList("test", "test", "wow", "quit", "tree", "tree");
Set<String> set = Bags.mutable.withAll(list).selectUnique();
System.out.println(set);
Outputs:
[wow, quit]
You can also construct a Bag
directly instead of creating a List
as follows:
MutableBag<String> bag =
Bags.mutable.with("test", "test", "wow", "quit", "tree", "tree");
MutableSet<String> set = bag.selectUnique();
Note: I am a committer for Eclipse Collections
来源:https://stackoverflow.com/questions/14225302/want-non-duplicate-elements-from-list