I have a method that returns Sets of sets.
Following is what I mean:
public static HashSet methodName(){
HashSet c= new HashSet();
c.add(x); //x is a HashSet of number
c.add(y); //y is a Hashset of numbers
return c;
}
After the method returns the collections, I enter it into an arraylist
ArrayList<HashSet> xxx= new ArrayList<Hashset>();
y=methodName();
xxx.add(y);
The method gets called couple of times and each time I enter sets of sets into the arraylist.
My question is. now I want to go through the arraylist and find the set that contains the smallest number of sets. How do I do that? Thanks so much in advance. Any help will be appreciated.
The size() method gives the cardinality of a HashSet. Simply write a Comparator<HashSet> and use Collections.max().
A simple way you to go through an array is through an Iterator. These are utilized in a foreach loop, which can be used when you know the type of elements used in an array (via generics). You can use that in your outer HashSet- containing ArrayList:
for (HashSet set : xxx) {
// you need to iterate over the elements in your HashSet here and determine which internal Set has the most elements
for ( Iterator iter = set.iterator(); iter.hasNext();) {
HashSet innerSet = (HashSet) iter.next();
// do the size test
}
}
Related
As I used Comparator for sorting a library after the author's name, I just coincidentally "found" something, which actually works perfectly, but I don't understand why. Firstly please have a look at my code:
public class Bookshelf{
Collection<Literature> shelf = new ArrayList<Literature>();
ArrayList<Literature> unsorted = (ArrayList<Literature>)shelf;
public void printShelf() {
Comparator<Literature> compareBySurname= new Comparator<Literature>() {
#Override
public int compare(Literature o1, Literature o2) {
return o1.author.surname.compareTo(o2.author.surname);
}
};
unsorted.sort(compareBySurname);
for (Literature c : shelf)
System.out.println(c);
}
}
As you can see, I am sorting the ArrayList "unsorted". But after I sort it, I am iterating through the Collection "shelf" and printing the elements of the Collection "shelf".And the output is a list of sorted elements by surname.
To achive my intention, I actually should iterate through the ArrayList "unsorted" and print the elements (of course this option works too). So my question is, why the first methode actually works too? :D So I am not sorting the Collection "shelf" directly, but I get a sorted list.
Thanks in advance!
ArrayList<Literature> unsorted = (ArrayList<Literature>)shelf; does not create a new ArrayList. It simply makes unsorted refer to the same ArrayList as shelf. They are not different objects. You want something like
ArrayList<Literature> unsorted = new ArrayList<>(shelf); // <-- a different List.
Because both lists share the same memory reference when you assign the list with the "=" operator. To have a new list with another reference, you must use the key name "new".
I am trying to present a simplified version of my requirement here for ease of understanding.
I have this class
public class MyClass {
private byte[] data1;
private byte[] data2;
private long hash1; // Hash value for data1
private long hash2; // Hash value for data2
// getter and setters }
Now I need to search between 2 List instances of this class, find how many hash1's match between the 2 instances and for all matches how many corresponding hash2's match. The 2 list will have about 10 million objects of MyClass.
Now I am planning to iterate over first list and search in the second one. Is there a way I can optimize the search by sorting or ordering in any particular way? Should I sort both list or only 1?
Best solution would be to iterate there is no faster solution than this. You can create Hashmap and take advantage that map does not add same key but then it has its own creation overload
sort only second, iterate over first and do binary search in second, sort O(nlogn) and binary search for n item O(nlogn)
or use hashset for second, iterate over first and search in second, O(n)
If you have to check all the elements, I think you should iterate over the first list and have a Hashmap for the second one as said AmitD.
You just have to correctly override equals and hashcode in your MyClass class. Finally, I will recomend you to use basic types as much as possible. For example, for the first list, instead of a list will be better to use a simple array.
Also, at the beginning you could select which of the two lists is the shorter one (if there's a difference in the size) and iterate over that one.
I think you should create a hashmap for one of the lists (say list1) -
Map<Long, MyClass> map = new HashMap<Long, MyClass>(list1.size());//specify the capacity
//populate map like - put(myClass.getHash1(), myClass) : for each element in the list
Now just iterate through the second list (there is no point in sorting both) -
int hash1MatchCount = 0;
int hash2MatchCount = 0;
for(MyClass myClass : list2) {
MyClass mc = map.get(myClass.getHash1());
if(mc != null) {
hash1MatchCount++;
if(myClass.getHash2() == mc.getHash2) {
hash2MatchCount++;
}
}
}
Note: Assuming that there is no problem regarding hash1 being duplicates.
I have a nested list like below (but it has 1,000's of the holder lists within the one main list). Say I need to sort the main list listEmailData by the value for each of its holder lists on the holder.get(2) index. I can't seem to figure out how to do this any advice is appreciated.
ArrayList listEmailData;
ArrayList holder = new ArrayList();
listEmailData.add(3)
listEmailData.add(323)
listEmailData.add(2342)
listEmailData.add(holder)
EDIT: To clarify, I have a list where each list entry contains a sub-list, within this sub-list a specific index contains a value that is a ranking. I need to sort the main list based on this ranking value within each sub-list.
2ND EDIT: Thanks for the help on this, got it working but its seems that its putting larger numbers first and large numbers later, I was hoping to reverse this so it goes from largest to smallest as I am
You should implement Comparator<T> to compare lists, then call
Collections.sort(listEmailData, comparator);
Your comparator would have to compare any two "sublists" - e.g. by fetching a particular value. For example:
public class ListComparator implements Comparator<List<Integer>>
{
private final int indexToCompare;
public ListComparator(int indexToCompare)
{
this.indexToCompare = indexToCompare;
}
public int compare(List<Integer> first, List<Integer> second)
{
// TODO: null checking
Integer firstValue = first.get(indexToCompare);
Integer secondValue = second.get(indexToCompare);
return firstValue.compareTo(secondValue);
}
}
Note that this is using generics - hopefully your real code is too.
I am storing Integer objects representing an index of objects I want to track. Later in my code I want to check to see if a particular object's index corresponds to one of those Integers I stored earlier. I am doing this by creating an ArrayList and creating a new Integer from the index of a for loop:
ArrayList<Integer> courseselectItems = new ArrayList();
//Find the course elements that are within a courseselect element and add their indicies to the ArrayList
for(int i=0; i<numberElementsInNodeList; i++) {
if (nodeList.item(i).getParentNode().getNodeName().equals("courseselect")) {
courseselectItems.add(new Integer(i));
}
}
I then want to check later if the ArrayList contains a particular index:
//Cycle through the namedNodeMap array to find each of the course codes
for(int i=0; i<numberElementsInNodeList; i++) {
if(!courseselectItems.contains(new Integer(i))) {
//Do Stuff
}
}
My question is, when I create a new Integer by using new Integer(i) will I be able to compare integers using ArrayList.contains()? That is to say, when I create a new object using new Integer(i), will that be the same as the previously created Integer object if the int value used to create them are the same?
I hope I didn't make this too unclear. Thanks for the help!
Yes, you can use List.contains() as that uses equals() and an Integer supports that when comparing to other Integers.
Also, because of auto-boxing you can simply write:
List<Integer> list = new ArrayList<Integer>();
...
if (list.contains(37)) { // auto-boxed to Integer
...
}
It's worth mentioning that:
List list = new ArrayList();
list.add(new Integer(37));
if (list.contains(new Long(37)) {
...
}
will always return false because an Integer is not a Long. This trips up most people at some point.
Lastly, try and make your variables that are Java Collections of the interface type not the concrete type so:
List<Integer> courseselectItems = new ArrayList();
not
ArrayList<Integer> courseselectItems = new ArrayList();
My question is, when I create a new Integer by using new Integer(i) will I be able to compare integers using ArrayList.contains()? That is to say, when I create a new object using new Integer(i), will that be the same as the previously created Integer object if the int value used to create them are the same?
The short answer is yes.
The long answer is ...
That is to say, when I create a new object using new Integer(i), will that be the same as the previously created Integer object if the int value used to create them are the same?
I assume you mean "... will that be the same instance as ..."? The answer to that is no - calling new will always create a distinct instance separate from the previous instance, even if the constructor parameters are identical.
However, despite having separate identity, these two objects will have equivalent value, i.e. calling .equals() between them will return true.
Collection.contains()
It turns out that having separate instances of equivalent value (.equals() returns true) is okay. The .contains() method is in the Collection interface. The Javadoc description for .contains() says:
http://java.sun.com/javase/6/docs/api/java/util/Collection.html#contains(java.lang.Object)
boolean contains(Object o)
Returns true if this collection
contains the specified element. More
formally, returns true if and only if
this collection contains at least one
element e such that (o==null ? e==null
: o.equals(e)).
Thus, it will do what you want.
Data Structure
You should also consider whether you have the right data structure.
Is the list solely about containment? is the order important? Do you care about duplicates? Since a list is order, using a list can imply that your code cares about ordering. Or that you need to maintain duplicates in the data structure.
However, if order is not important, if you don't want or won't have duplicates, and if you really only use this data structure to test whether contains a specific value, then you might want to consider whether you should be using a Set instead.
Short answer is yes, you should be able to do ArrayList.contains(new Integer(14)), for example, to see if 14 is in the list. The reason is that Integer overrides the equals method to compare itself correctly against other instances with the same value.
Yes it will, because List.contains() use the equals() method of the object to be compared. And Integer.equals() does compare the integer value.
As cletus and DJ mentioned, your approach will work.
I don't know the context of your code, but if you don't care about the particular indices, consider the following style also:
List<Node> courseSelectNodes = new ArrayList<Node>();
//Find the course elements that are within a courseselect element
//and add them to the ArrayList
for(Node node : numberElementsInNodeList) {
if (node.getParentNode().getNodeName().equals("courseselect")) {
courseSelectNodes.add(node);
}
}
// Do stuff with courseSelectNodes
for(Node node : courseSelectNodes) {
//Do Stuff
}
I'm putting my answer in the form of a (passing) test, as an example of how you might research this yourself. Not to discourage you from using SO - it's great - just to try to promote characterization tests.
import java.util.ArrayList;
import junit.framework.TestCase;
public class ContainsTest extends TestCase {
public void testContains() throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
assertFalse(list.contains(new Integer(17)));
list.add(new Integer(17));
assertTrue(list.contains(new Integer(17)));
}
}
Yes, automatic boxing occurs but this results in a performance penalty. Its not clear from your example why you would want to solve the problem in this manner.
Also, because of boxing, creating the Integer class by hand is superfluous.
What is the best way to get value from java.util.Collection by index?
You shouldn't. a Collection avoids talking about indexes specifically because it might not make sense for the specific collection. For example, a List implies some form of ordering, but a Set does not.
Collection<String> myCollection = new HashSet<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = World
elem = Hello
myCollection.toArray()[0] = World
whilst:
myCollection = new ArrayList<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = Hello
elem = World
myCollection.toArray()[0] = Hello
Why do you want to do this? Could you not just iterate over the collection?
I agree with Matthew Flaschen's answer and just wanted to show examples of the options for the case you cannot switch to List (because a library returns you a Collection):
List list = new ArrayList(theCollection);
list.get(5);
Or
Object[] list2 = theCollection.toArray();
doSomethingWith(list[2]);
If you know what generics is I can provide samples for that too.
Edit: It's another question what the intent and semantics of the original collection is.
In general, there is no good way, as Collections are not guaranteed to have fixed indices. Yes, you can iterate through them, which is how toArray (and other functions) work. But the iteration order isn't necessarily fixed, and if you're trying to index into a general Collection, you're probably doing something wrong. It would make more sense to index into a List.
I agree that this is generally a bad idea. However, Commons Collections had a nice routine for getting the value by index if you really need to:
CollectionUtils.get(collection, index)
You must either wrap your collection in a list (new ArrayList(c)) or use c.toArray() since Collections have no notion of "index" or "order".
Convert the collection into an array by using function
Object[] toArray(Object[] a)
It would be just as convenient to simply convert your collection into a list whenever it updates. But if you are initializing, this will suffice:
for(String i : collectionlist){
arraylist.add(i);
whateverIntID = arraylist.indexOf(i);
}
Be open-minded.
you definitively want a List:
The List interface provides four methods for positional (indexed) access to list elements.
Lists (like Java arrays) are zero based.
Also
Note that these operations may execute in time proportional to the index value for some
implementations (the LinkedList class, for example). Thus, iterating over the elements in a > list is typically preferable to indexing through it if the caller does not know the
implementation.
If you need the index in order to modify your collection you should note that List provides a special ListIterator that allow you to get the index:
List<String> names = Arrays.asList("Davide", "Francesco", "Angelocola");
ListIterator<String> i = names.listIterator();
while (i.hasNext()) {
System.out.format("[%d] %s\n", i.nextIndex(), i.next());
}
use for each loop...
ArrayList<Character> al = new ArrayList<>();
String input="hello";
for (int i = 0; i < input.length(); i++){
al.add(input.charAt(i));
}
for (Character ch : al) {
System.Out.println(ch);
}
If your Collection is a List, simply cast it as a List and call get(final int index). Otherwise, it might make sense to consider finding the nth element in an ordered set, for example if it's a LinkedHashSet respecting insertion order (keep in mind that it's possible to create such an instance not respecting insertion order), you can use Collection.stream().skip(index).limit(1).findFirst().orElse(null).
You can get the value from collection using for-each loop or using iterator interface. For a Collection c
for (<ElementType> elem: c)
System.out.println(elem);
or Using Iterator Interface
Iterator it = c.iterator();
while (it.hasNext())
System.out.println(it.next());