Picking a random element from a set - java

How do I pick a random element from a set?
I'm particularly interested in picking a random element from a
HashSet or a LinkedHashSet, in Java.
Solutions for other languages are also welcome.

int size = myHashSet.size();
int item = new Random().nextInt(size); // In real life, the Random object should be rather more shared than this
int i = 0;
for(Object obj : myhashSet)
{
if (i == item)
return obj;
i++;
}

A somewhat related Did You Know:
There are useful methods in java.util.Collections for shuffling whole collections: Collections.shuffle(List<?>) and Collections.shuffle(List<?> list, Random rnd).

In Java 8:
static <E> E getRandomSetElement(Set<E> set) {
return set.stream().skip(new Random().nextInt(set.size())).findFirst().orElse(null);
}

Fast solution for Java using an ArrayList and a HashMap: [element -> index].
Motivation: I needed a set of items with RandomAccess properties, especially to pick a random item from the set (see pollRandom method). Random navigation in a binary tree is not accurate: trees are not perfectly balanced, which would not lead to a uniform distribution.
public class RandomSet<E> extends AbstractSet<E> {
List<E> dta = new ArrayList<E>();
Map<E, Integer> idx = new HashMap<E, Integer>();
public RandomSet() {
}
public RandomSet(Collection<E> items) {
for (E item : items) {
idx.put(item, dta.size());
dta.add(item);
}
}
#Override
public boolean add(E item) {
if (idx.containsKey(item)) {
return false;
}
idx.put(item, dta.size());
dta.add(item);
return true;
}
/**
* Override element at position <code>id</code> with last element.
* #param id
*/
public E removeAt(int id) {
if (id >= dta.size()) {
return null;
}
E res = dta.get(id);
idx.remove(res);
E last = dta.remove(dta.size() - 1);
// skip filling the hole if last is removed
if (id < dta.size()) {
idx.put(last, id);
dta.set(id, last);
}
return res;
}
#Override
public boolean remove(Object item) {
#SuppressWarnings(value = "element-type-mismatch")
Integer id = idx.get(item);
if (id == null) {
return false;
}
removeAt(id);
return true;
}
public E get(int i) {
return dta.get(i);
}
public E pollRandom(Random rnd) {
if (dta.isEmpty()) {
return null;
}
int id = rnd.nextInt(dta.size());
return removeAt(id);
}
#Override
public int size() {
return dta.size();
}
#Override
public Iterator<E> iterator() {
return dta.iterator();
}
}

This is faster than the for-each loop in the accepted answer:
int index = rand.nextInt(set.size());
Iterator<Object> iter = set.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
The for-each construct calls Iterator.hasNext() on every loop, but since index < set.size(), that check is unnecessary overhead. I saw a 10-20% boost in speed, but YMMV. (Also, this compiles without having to add an extra return statement.)
Note that this code (and most other answers) can be applied to any Collection, not just Set. In generic method form:
public static <E> E choice(Collection<? extends E> coll, Random rand) {
if (coll.size() == 0) {
return null; // or throw IAE, if you prefer
}
int index = rand.nextInt(coll.size());
if (coll instanceof List) { // optimization
return ((List<? extends E>) coll).get(index);
} else {
Iterator<? extends E> iter = coll.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
}
}

If you want to do it in Java, you should consider copying the elements into some kind of random-access collection (such as an ArrayList). Because, unless your set is small, accessing the selected element will be expensive (O(n) instead of O(1)). [ed: list copy is also O(n)]
Alternatively, you could look for another Set implementation that more closely matches your requirements. The ListOrderedSet from Commons Collections looks promising.

In Java:
Set<Integer> set = new LinkedHashSet<Integer>(3);
set.add(1);
set.add(2);
set.add(3);
Random rand = new Random(System.currentTimeMillis());
int[] setArray = (int[]) set.toArray();
for (int i = 0; i < 10; ++i) {
System.out.println(setArray[rand.nextInt(set.size())]);
}

List asList = new ArrayList(mySet);
Collections.shuffle(asList);
return asList.get(0);

This is identical to accepted answer (Khoth), but with the unnecessary size and i variables removed.
int random = new Random().nextInt(myhashSet.size());
for(Object obj : myhashSet) {
if (random-- == 0) {
return obj;
}
}
Though doing away with the two aforementioned variables, the above solution still remains random because we are relying upon random (starting at a randomly selected index) to decrement itself toward 0 over each iteration.

Clojure solution:
(defn pick-random [set] (let [sq (seq set)] (nth sq (rand-int (count sq)))))

Java 8+ Stream:
static <E> Optional<E> getRandomElement(Collection<E> collection) {
return collection
.stream()
.skip(ThreadLocalRandom.current()
.nextInt(collection.size()))
.findAny();
}
Based on the answer of Joshua Bone but with slight changes:
Ignores the Streams element order for a slight performance increase in parallel operations
Uses the current thread's ThreadLocalRandom
Accepts any Collection type as input
Returns the provided Optional instead of null

Perl 5
#hash_keys = (keys %hash);
$rand = int(rand(#hash_keys));
print $hash{$hash_keys[$rand]};
Here is one way to do it.

C++. This should be reasonably quick, as it doesn't require iterating over the whole set, or sorting it. This should work out of the box with most modern compilers, assuming they support tr1. If not, you may need to use Boost.
The Boost docs are helpful here to explain this, even if you don't use Boost.
The trick is to make use of the fact that the data has been divided into buckets, and to quickly identify a randomly chosen bucket (with the appropriate probability).
//#include <boost/unordered_set.hpp>
//using namespace boost;
#include <tr1/unordered_set>
using namespace std::tr1;
#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;
int main() {
unordered_set<int> u;
u.max_load_factor(40);
for (int i=0; i<40; i++) {
u.insert(i);
cout << ' ' << i;
}
cout << endl;
cout << "Number of buckets: " << u.bucket_count() << endl;
for(size_t b=0; b<u.bucket_count(); b++)
cout << "Bucket " << b << " has " << u.bucket_size(b) << " elements. " << endl;
for(size_t i=0; i<20; i++) {
size_t x = rand() % u.size();
cout << "we'll quickly get the " << x << "th item in the unordered set. ";
size_t b;
for(b=0; b<u.bucket_count(); b++) {
if(x < u.bucket_size(b)) {
break;
} else
x -= u.bucket_size(b);
}
cout << "it'll be in the " << b << "th bucket at offset " << x << ". ";
unordered_set<int>::const_local_iterator l = u.begin(b);
while(x>0) {
l++;
assert(l!=u.end(b));
x--;
}
cout << "random item is " << *l << ". ";
cout << endl;
}
}

Solution above speak in terms of latency but doesn't guarantee equal probability of each index being selected.
If that needs to be considered, try reservoir sampling. http://en.wikipedia.org/wiki/Reservoir_sampling. Collections.shuffle() (as suggested by few) uses one such algorithm.

Since you said "Solutions for other languages are also welcome", here's the version for Python:
>>> import random
>>> random.choice([1,2,3,4,5,6])
3
>>> random.choice([1,2,3,4,5,6])
4

Can't you just get the size/length of the set/array, generate a random number between 0 and the size/length, then call the element whose index matches that number? HashSet has a .size() method, I'm pretty sure.
In psuedocode -
function randFromSet(target){
var targetLength:uint = target.length()
var randomIndex:uint = random(0,targetLength);
return target[randomIndex];
}

PHP, assuming "set" is an array:
$foo = array("alpha", "bravo", "charlie");
$index = array_rand($foo);
$val = $foo[$index];
The Mersenne Twister functions are better but there's no MT equivalent of array_rand in PHP.

Icon has a set type and a random-element operator, unary "?", so the expression
? set( [1, 2, 3, 4, 5] )
will produce a random number between 1 and 5.
The random seed is initialized to 0 when a program is run, so to produce different results on each run use randomize()

In C#
Random random = new Random((int)DateTime.Now.Ticks);
OrderedDictionary od = new OrderedDictionary();
od.Add("abc", 1);
od.Add("def", 2);
od.Add("ghi", 3);
od.Add("jkl", 4);
int randomIndex = random.Next(od.Count);
Console.WriteLine(od[randomIndex]);
// Can access via index or key value:
Console.WriteLine(od[1]);
Console.WriteLine(od["def"]);

Javascript solution ;)
function choose (set) {
return set[Math.floor(Math.random() * set.length)];
}
var set = [1, 2, 3, 4], rand = choose (set);
Or alternatively:
Array.prototype.choose = function () {
return this[Math.floor(Math.random() * this.length)];
};
[1, 2, 3, 4].choose();

In lisp
(defun pick-random (set)
(nth (random (length set)) set))

How about just
public static <A> A getRandomElement(Collection<A> c, Random r) {
return new ArrayList<A>(c).get(r.nextInt(c.size()));
}

For fun I wrote a RandomHashSet based on rejection sampling. It's a bit hacky, since HashMap doesn't let us access it's table directly, but it should work just fine.
It doesn't use any extra memory, and lookup time is O(1) amortized. (Because java HashTable is dense).
class RandomHashSet<V> extends AbstractSet<V> {
private Map<Object,V> map = new HashMap<>();
public boolean add(V v) {
return map.put(new WrapKey<V>(v),v) == null;
}
#Override
public Iterator<V> iterator() {
return new Iterator<V>() {
RandKey key = new RandKey();
#Override public boolean hasNext() {
return true;
}
#Override public V next() {
while (true) {
key.next();
V v = map.get(key);
if (v != null)
return v;
}
}
#Override public void remove() {
throw new NotImplementedException();
}
};
}
#Override
public int size() {
return map.size();
}
static class WrapKey<V> {
private V v;
WrapKey(V v) {
this.v = v;
}
#Override public int hashCode() {
return v.hashCode();
}
#Override public boolean equals(Object o) {
if (o instanceof RandKey)
return true;
return v.equals(o);
}
}
static class RandKey {
private Random rand = new Random();
int key = rand.nextInt();
public void next() {
key = rand.nextInt();
}
#Override public int hashCode() {
return key;
}
#Override public boolean equals(Object o) {
return true;
}
}
}

The easiest with Java 8 is:
outbound.stream().skip(n % outbound.size()).findFirst().get()
where n is a random integer. Of course it is of less performance than that with the for(elem: Col)

With Guava we can do a little better than Khoth's answer:
public static E random(Set<E> set) {
int index = random.nextInt(set.size();
if (set instanceof ImmutableSet) {
// ImmutableSet.asList() is O(1), as is .get() on the returned list
return set.asList().get(index);
}
return Iterables.get(set, index);
}

In Mathematica:
a = {1, 2, 3, 4, 5}
a[[ ⌈ Length[a] Random[] ⌉ ]]
Or, in recent versions, simply:
RandomChoice[a]
Random[] generates a pseudorandom float between 0 and 1. This is multiplied by the length of the list and then the ceiling function is used to round up to the next integer. This index is then extracted from a.
Since hash table functionality is frequently done with rules in Mathematica, and rules are stored in lists, one might use:
a = {"Badger" -> 5, "Bird" -> 1, "Fox" -> 3, "Frog" -> 2, "Wolf" -> 4};

PHP, using MT:
$items_array = array("alpha", "bravo", "charlie");
$last_pos = count($items_array) - 1;
$random_pos = mt_rand(0, $last_pos);
$random_item = $items_array[$random_pos];

you can also transfer the set to array use array
it will probably work on small scale i see the for loop in the most voted answer is O(n) anyway
Object[] arr = set.toArray();
int v = (int) arr[rnd.nextInt(arr.length)];

If you really just want to pick "any" object from the Set, without any guarantees on the randomness, the easiest is taking the first returned by the iterator.
Set<Integer> s = ...
Iterator<Integer> it = s.iterator();
if(it.hasNext()){
Integer i = it.next();
// i is a "random" object from set
}

A generic solution using Khoth's answer as a starting point.
/**
* #param set a Set in which to look for a random element
* #param <T> generic type of the Set elements
* #return a random element in the Set or null if the set is empty
*/
public <T> T randomElement(Set<T> set) {
int size = set.size();
int item = random.nextInt(size);
int i = 0;
for (T obj : set) {
if (i == item) {
return obj;
}
i++;
}
return null;
}

Related

How to add an integer to a set while iterating?

I have a set of sets of integers: Set<Set<Integer>>.
I need to add integers to the set of sets as if it were a double array. So add(2,3) would have to add integer 3 to the 2nd set.
I know a set is not very suitable for this operation but it's not my call.
The commented line below clearly does not work but it shows the intention.
My question is how to add an integer to a set while iterating?
If it's necessary to identify each set, how would one do this?
#Override
public void add(int a, int b) {
if (!isValidPair(a, b)) {
throw new IllegalStateException("!isValidPair does not hold for (a,b)");
}
Iterator<Set<Integer>> it = relation.iterator();
int i = 0;
while (it.hasNext() && i <= a) {
//it.next().add(b);
i++;
}
}
One fundamental things you should be aware of, for which makes all existing answer in this question not working:
Once an object is added in a Set (similarly, as key in Map), it is not supposed to change (at least not in aspects that will change its equals() and hashCode()). The "Uniqueness" checking is done only when you add the object into the Set.
For example
Set<Set<Integer>> bigSet = new HashSet<>();
Set<Integer> v1 = new HashSet<>(Arrays.asList(1,2));
bigSet.add(v1);
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2)))); // True
v1.add(3);
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2)))); // False!!
System.out.println("contains " + bigSet.contains(new HashSet<>(Arrays.asList(1,2,3)))); // False!!
You can see how the set is corrupted. It contains a [1,2,3] but contains() does not work, neither for [1,2] nor [1,2,3].
Another fundamental thing is, your so-called '2nd set' may not make sense. Set implementation like HashSet maintain the values in arbitrary order.
So, with these in mind, what you may do is:
First find the n-th value, and remove it
add the value into the removed value set
re-add the value set.
Something like this (pseudo code again):
int i = 0;
Set<Integer> setToAdd = null;
for (Iterator itr = bigSet.iterator; itr.hasNext(); ++i) {
Set<Integer> s = itr.next();
if (i == inputIndex) {
// remove the set first
itr.remove();
setToAdd = s;
break;
}
}
// update the set and re-add it back
if (setToAdd != null) {
setToAdd.add(inputNumber);
bigSet.add(setToAdd);
}
Use a for-each loop and make your life easier.
public boolean add(int index, int value) {
// because a and b suck as variable names
if (index < 0 || index >= values.size()) {
return false;
}
int iter = 0;
for (Set<Integer> values : relation) {
if (iter++ == index) {
return values.add(value):
}
}
return false;
}
Now all you have to figure out is what to do if relation is unordered, as a Set or a relation are, because in that case a different Set<Integer> could match the same index each time the loop executes.
Use can use Iterators of Guava library like this :
#Override
public void add(int a, int b) {
if (!isValidPair(a, b)) {
throw new IllegalStateException("!isValidPair does not hold for (a,b)");
}
Iterators.get(relation.iterator(), a).add(b);
}
Edit : without Guava:
Iterator<Set<Integer>> iterator = relation.iterator();
for(int i = 0; i < a && iterator.hasNext(); ++i) {
iterator.next();
}
if(iterator.hasNext()) {
iterator.next().add(b);
}

Java smallest partition of common elements (in the same order) of two or more lists

I'm looking for a quick and smart way to find up until where two lists are equal. In other words I need to find the smallest partition containing common elements in the same order of two or more lists.
It might sound a bit confusing but here is an example of what I want to achieve:
List 1: A, B, C, L, M Z
List 2: A, B, C, K, F
Output -> List 3: A, B, C
I need to use this in a recursive method which should be called with large inputs and all the solutions I've come up with are a bit too slow.
Thanks for your answers in advance
EDIT:
Please excuse me for being unclear. This is my first question and english is not my first language.
Let me explain the problem in a better way. I need to find the intersection of two or more lists starting from the first element of the lists. Please note that elements must be in the same order so it's not exactly an intersection but more like a partition.
the "recursive" thing was just to say that I need to include this in a recursive method which will run many times so I would like the solution to be as fast as possibile as to not lose a lot of time.
Working on an answer that appears to have been deleted I came up with my own solution:
List<String> list1 = new ArrayList<>(Arrays.asList("ciao", "come"));
List<String> list2 = new ArrayList<>(Arrays.asList("ciao", "come", "va"));
List<String> list3 = new ArrayList<>(Arrays.asList("ciao", "come", "va", "?", "tutto", "ok"));
List<List<String>> allLists = new ArrayList<>();
allLists.addAll(Arrays.asList(list1, list2, list3));
int min = Integer.MAX_VALUE;
int listIndex = 0;
for(List<String> list : allLists){
if(min > list.size()){
min = list.size();
listIndex = allLists.indexOf(list);
}
}
int index = 0;
boolean same = true;
while(index<min && same == true) {
String element = allLists.get(listIndex).get(index);
for(List<String> list : allLists){
if(!list.get(index).equals(element)){
same = false;
break;
}
element = allLists.get(listIndex).get(index);
}
if(same == true) ++index;
}
System.out.println("OUTPUT:" + allLists.get(listIndex).subList(0, index));
----> Output: ciao, come
EDIT2:
And also garnful's solution works like a charm and I find it way clearer than mine. Thanks everybody
This should do the work, and hopefully be quite okay regarding the performance:
public List<String> getEqualsPart(List<String>[] listsToCheck) {
if (listsToCheck.length == 0) {
return Collections.emptyList();
}
int minLength = getShortesListLength(listsToCheck);
if (minLength == 0) {
return Collections.emptyList();
}
return getEqualPartsForIndex(listsToCheck, 0, minLength, new ArrayList<String>());
}
private int getShortesListLength(List<String>[] listsToCheck) {
int min = Integer.MAX_VALUE;
for (List<String> currentList : listsToCheck) {
min = Math.min(min, currentList.size());
}
return min;
}
private List<String> getEqualPartsForIndex(List<String>[] listsToCheck, int index, int minLength,
List<String> result) {
if (index == minLength) {
return result;
}
Set<String> setForIndex = new HashSet<>();
Arrays.stream(listsToCheck).forEach(list -> setForIndex.add(list.get(index)));
if (setForIndex.size() > 1) {
return result;
} else {
result.add(setForIndex.iterator().next());
return getEqualPartsForIndex(listsToCheck, index + 1, minLength, result);
}
}`
Try:
public List<E> equalUntil(List<E> l1, List<E> l2) {
return equalUntilRec(l1.iterator(), l2.iterator(), new ArrayList<E>());
}
private int equalUntilRec(Iterator<E> it1, Iterator<E> it2, List<E> acc) {
if(!it1.hasNext() || !it2.hasNext()) {
return acc;
} else {
E e1 = it1.next();
E e2 = it2.next();
if(!e1.equals(e2)) {
return acc;
}
acc.add(e1);
return equalUntilRec(it1, it2, acc);
}
}

How to check to see which value of a list is highest another another list

This is my situation: I have list A of values. I also have list B which contains a hierarchy of ranks. The first being of the highest, last being of the lowest. List A will contain one, some, or all of the values from list B. I want to see which value from list A is of the highest degree (or lowest index) on list B. How would I do this best?
Just in case its still unclear, this is an example:
List A: Merchant, Peasant, Queen
List B: King, Queen, Knight, Merchant, Peasant
I'd want the method to spit out Queen in this case
Assuming List B is already sorted from Top Rank -> Bottom rank, one arbitary way you could solve it is with
public static void main (String[] args) throws Exception {
String[] firstList = { "Merchant", "Peasant", "Queen" };
String[] secondList = { "King", "Queen", "Knight", "Merchant", "Peasant" };
for (String highRank : secondList) {
for (String lowRank : firstList) {
if (highRank.equalsIgnoreCase(lowRank)) {
System.out.println(highRank);
return;
}
}
}
}
What you are describing is called a "partial ordering", and the proper way to implement the behavior you're looking for in Java is with a Comparator that defines the ordering; something like:
public class PartialOrdering<T> implements Comparator<T> {
private final Map<T, Integer> listPositions = new HashMap<>();
public PartialOrdering(List<T> elements) {
for (int i = 0; i < elements.size(); i++) {
listPositions.put(elements.get(i), i);
}
}
public int compare(T a, T b) {
Integer aPos = listPositions.get(a);
Integer bPos = listPositions.get(b);
if (aPos == null || bPos == null) {
throw new IllegalArgumentException(
"PartialOrdering can only compare elements it's aware of.");
}
return Integer.compare(aPos, bPos);
}
}
You can then simply call Collections.max() to find the largest value in your first list.
This is much more efficient than either of the other answers, which are both O(n^2) and don't handle unknown elements coherently (they assume we have a total ordering).
Even better than implementing your own PartialOrdering, however, is to use Guava's Ordering class, which provides an efficient partial ordering and a number of other useful tools. With Guava all you need to do is:
// Or store the result of Ordering.explicit() if you need to reuse it
Ordering.explicit(listB).max(listA);
I think this might work give it a Try:
function int getHighest(List<String> listA, List<String> listB)
{
int index = 0;
int max = 100;
int tmpMax = 0;
for(String test:lista)
{
for(int i =0;i<listb.size();++i)
{
if(list.get(i).equals(test))
{
tmpMax = index;
}
}
if(tmpMax < max) max = tmpMax;
++index;
}
return max;
}

creating java generic data structure

I am building a data structure to learn more about java. I understand this program might be useless.
Here's what I want. I want to create a data structure that store smallest 3 values. if value is high, then ignore it. When storing values than I also want to put them in correct place so I don't have to sort them later. I can enter values by calling the add method.
so let's say I want to add 20, 10, 40, 30 than the result will be [10,20,30]. note I can only hold 3 smallest values and it store them as I place them.
I also understand that there are a lot of better ways for doing this but again this is just for learning purposes.
Question: I need help creating add method. I wrote some code but I am getting stuck with add method. Please help.
My Thinking: we might have to use a Iterator in add method?
public class MyJavaApp {
public static void main(String[] args){
MyClass<Integer> m = new MyClass<Integer>(3);
m.add(10);
m.add(20);
m.add(30);
m.add(40);
}
}
public class MyClass<V extends Comparable<V>> {
private V v[];
public MyClass(int s){
this.v = (V[])new Object[s];
}
public void add(V a){
}
}
Here is a rough sketch of the add method you have to implement.
You have to use the appropriate implementation of the compareTo method when comparing elements.
public void add(V a){
V temp = null;
if(a.compareTo( v[0]) == -1 ){
/*
keeping the v[0] in a temp variable since, v[0] could be the second
smallest value or the third smallest value.
Therefore call add method again to assign it to the correct
position.
*/
temp = v[0];
v[0] = a;
add(temp);
}else if(a.compareTo(v[0]) == 1 && a.compareTo(v[1]) == -1){
temp = v[1];
v[1] = a;
add(temp);
}else if(a.compareTo(v[1]) == 1 && a.compareTo(v[2]) == -1){
temp = v[2];
v[2] = a;
add(temp);
}
}
Therefore the v array will contain the lowerest elements.
Hope this helps.
A naive, inefficient approach would be (as you suggest) to iterate through the values and add / remove based on what you find:
public void add(Integer a)
{
// If fewer than 3 elements in the list, add and we're done.
if (m.size() < 3)
{
m.add(a);
return;
}
// If there's 3 elements, find the maximum.
int max = Integer.MIN_VALUE;
int index = -1;
for (int i=0; i<3; i++) {
int v = m.get(i);
if (v > max) {
max = v;
index = i;
}
}
// If a is less than the max, we need to add it and remove the existing max.
if (a < max) {
m.remove(index);
m.add(a);
}
}
Note: this has been written for Integer, not a generic type V. You'll need to generalise. It also doesn't keep the list sorted - another of your requirements.
Here's an implementation of that algorithm. It consists of looking for the right place to insert. Then it can be optimized for your requirements:
Don't bother looking past the size you want
Don't add more items than necessary
Here's the code. I added the toString() method for convenience. Only the add() method is interesting. Also this implementation is a bit more flexible as it respects the size you give to the constructor and doesn't assume 3.
I used a List rather than an array because it makes dealing with generics a lot easier. You'll find that using an array of generics makes using your class a bit more ugly (i.e. you have to deal with type erasure by providing a Class<V>).
import java.util.*;
public class MyClass<V extends Comparable<V>> {
private int s;
private List<V> v;
public MyClass(int s) {
this.s = s;
this.v = new ArrayList<V>(s);
}
public void add(V a) {
int i=0;
int l = v.size();
// Find the right index
while(i<l && v.get(i).compareTo(a) < 0) i++;
if(i<s) {
v.add(i, a);
// Truncate the list to make sure we don't store more values than needed
if(v.size() > s) v.remove(v.size()-1);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for(V item : v) {
result.append(item).append(',');
}
return result.toString();
}
}

Is it possible to find out if a value exists twice in an arraylist?

I have an integer arraylist..
ArrayList <Integer> portList = new ArrayList();
I need to check if a specific integer has already been entered twice. Is this possible in Java?
You could use something like this to see how many times a specific value is there:
System.out.println(Collections.frequency(portList, 1));
// There can be whatever Integer, and I use 1, so you can understand
And to check if a specific value is there more than once you could use something like this:
if ( (Collections.frequency(portList, x)) > 1 ){
System.out.println(x + " is in portList more than once ");
}
My solution
public static boolean moreThanOnce(ArrayList<Integer> list, int searched)
{
int numCount = 0;
for (int thisNum : list) {
if (thisNum == searched)
numCount++;
}
return numCount > 1;
}
If you are looking to do this in one method, then no. However, you could do it in two steps if you need to simply find out if it exists at least more than once in the List. You could do
int first = list.indexOf(object)
int second = list.lastIndexOf(object)
// Don't forget to also check to see if either are -1, the value does not exist at all.
if (first == second) {
// No Duplicates of object appear in the list
} else {
// Duplicate exists
}
This will tell you if you have at least two same values in your ArrayList:
int first = portList.indexOf(someIntValue);
int last = portList.lastIndexOf(someIntValue);
if (first != -1 && first != last) {
// someIntValue exists more than once in the list (not sure how many times though)
}
If you really want to know how many duplicates of a given value you have, you need to iterate through the entire array. Something like this:
/**
* Will return a list of all indexes where the given value
* exists in the given array. The list will be empty if the
* given value does not exist at all.
*
* #param List<E> list
* #param E value
* #return List<Integer> a list of indexes in the list
*/
public <E> List<Integer> collectFrequency(List<E> list, E value) {
ArrayList<Integer> freqIndex = new ArrayList<Integer>();
E item;
for (int i=0, len=list.size(); i<len; i++) {
item = list.get(i);
if ((item == value) || (null != item && item.equals(value))) {
freqIndex.add(i);
}
}
return freqIndex;
}
if (!collectFrequency(portList, someIntValue).size() > 1) {
// Duplicate value
}
Or using the already availble method:
if (Collections.frequency(portList, someIntValue) > 1) {
// Duplicate value
}
Set portSet = new HashSet<Integer>();
portSet.addAll(portList);
boolean listContainsDuplicates = portSet.size() != portList.size();
I used the following solution to find out whether an ArrayList contains a number more than once. This solution comes very close to the one listed by user3690146, but it does not use a helper variable at all. After running it, you get "The number is listed more than once" as a return message.
public class Application {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(4);
list.add(8);
list.add(1);
list.add(8);
int number = 8;
if (NumberMoreThenOnceInArray(list, number)) {
System.out.println("The number is listed more than once");
} else {
System.out.println("The number is not listed more than once");
}
}
public static boolean NumberMoreThenOnceInArray(ArrayList<Integer> list, int whichNumber) {
int numberCounter = 0;
for (int number : list) {
if (number == whichNumber) {
numberCounter++;
}
}
if (numberCounter > 1) {
return true;
}
return false;
}
}
Here is my solution (in Kotlin):
// getItemsMoreThan(list, 2) -> [4.45, 333.45, 1.1, 4.45, 333.45, 2.05, 4.45, 333.45, 2.05, 4.45] -> {4.45=4, 333.45=3}
// getItemsMoreThan(list, 1)-> [4.45, 333.45, 1.1, 4.45, 333.45, 2.05, 4.45, 333.45, 2.05, 4.45] -> {4.45=4, 333.45=3, 2.05=2}
fun getItemsMoreThan(list: List<Any>, moreThan: Int): Map<Any, Int> {
val mapNumbersByElement: Map<Any, Int> = getHowOftenItemsInList(list)
val findItem = mapNumbersByElement.filter { it.value > moreThan }
return findItem
}
// Return(map) how often an items is list.
// E.g.: [16.44, 200.00, 200.00, 33.33, 200.00, 0.00] -> {16.44=1, 200.00=3, 33.33=1, 0.00=1}
fun getHowOftenItemsInList(list: List<Any>): Map<Any, Int> {
val mapNumbersByItem = list.groupingBy { it }.eachCount()
return mapNumbersByItem
}
By looking at the question, we need to find out whether a value exists twice in an ArrayList. So I believe that we can reduce the overhead of "going through the entire list just to check whether the value only exists twice" by doing the simple check below.
public boolean moreThanOneMatch(int number, ArrayList<Integer> list) {
int count = 0;
for (int num : list) {
if (num == number) {
count ++ ;
if (count == 2) {
return true;
}
}
}
return false;
}

Categories