Iterating over HashSet with for each - java

I'm trying to iterate over the Integer objects of a HashSet and I want to count the number of times an element occurs. this is my method so far
public int freq(int element) {
int numElements = 0;
for (int atPos : mySet){
if (mySet.atPos == element){ //says atPos cannot be resolved to a field
numElements++;
}
}
return numElements;
}
would it be better to use an iterator to iterate over the elements? How do I fix my
mySet.atPos
line?
This is where I initialize my HashSet
private HashSet <Integer> mySet = new HashSet<Integer>();

A Set cannot contain duplicate elements. Therefore you will always get a count of 0 or 1 for your element.
For any collection, you can get the frequency of the elements with:
public int freq(int element) {
return Collections.frequency(mySet, element);
}
Not sure you'd want to make a method out of it ...

Your issue is a simple misunderstanding of how you can use variables. int atPos and mySet.atPos do not refer to the same thing. The former refers to a local variable, the latter is looking for a public member of field of an instance of a set called the same thing.
You are trying to access this field:
public class HashSet
{
public int atPos; //<<<
}
but, when we think of it this way, obviously that field does not exist in HashSet!
All you need to do is get rid of mySet. and your code will work.
if (atPos == element){
numElements++;
}
Would it be better to use an iterator to iterate over the elements?
No, there's no benefit to using an iterator in this situation. A for each is more readable.
As others have noted, because sets will never contain duplicates, your numElements will actually only ever be one or zero. As such, you could actually write your function very compactly as:
public int freq(int element) {
if (myset.contains(element)) {
return 1;
}
else {
return 0;
}
}
Or even better using the ternary operator:
public int freq(int element) {
return myset.contains(element) ? 1 : 0;
}

Related

Passing method of one class into another [duplicate]

This question already has answers here:
Passing a method from another class
(4 answers)
Closed 5 years ago.
My problem is that I need to getSymbol from Element class.
I would normally establish an object in PeriodicTable like this:
Element e = new Element();
then use e.getSymbol within method in order to use it for comparison.
So, in order to complete first task and print entire list of elements, I declared an array within PeriodicTable like this:
Element[] objects = new Element[ARRAY_SIZE];
I'm guessing I declared it correctly, as it does run entire list of elements.
Again, I am having problems getting getSymbol into my method in PeriodicTable.
Any helpful suggestions, please?
For this method, a user will input a symbol for an element. The method will search for the element and return its index (in the array). Then, it will use the index to display that single element and all of its other information, using the toString method from the Element class.
public int searchBySymbol(String sym)
{
int index = 0;
boolean found = false;
for (int i = 0; i < objects.length; i++)
{
objects[i] = objects.getSymbol;
}
while (index < objects.length && !found)
{
if (objects[index].equals(sym))
{
found = true;
}
else
{
index++;
}
}
if(found)
{
System.out.println("Found at position: " + index);
System.out.println(objects[index].toString());
}
else
{
System.out.println("Not found");
}
}
You definitely don't need two loops in there first of all, there are two solutions to this:
(Recommended) If searching Elements by symbol will be the your main way of looking up Elements, consider using a HashMap to contain the data rather than an Element array as HashMaps allow look up of objects by a key e.g. HashMap<String, Element>. Lookup the HashMap API or check this example: http://beginnersbook.com/2013/12/hashmap-in-java-with-example/
(Quick fix) Rather than using two loops to get the field and compare, in Java it is good practice to define accessor methods such as getSymbol() and return the field rather than directly accessing it. Using this method you can simplify your code into...
for (Element e : objects) {
if (e.getSymbol().equals(sym) {
return true;
}
}
//return false after the loop omits the need for an explicit boolean variable`
Edit: Usual for loop construct for index access. The index number is essentially tracked by the iterator variable int i so you do not need a separate variable to track it.
for (int i = 0; i < objects.length; i++) {
if (objects[i].getSymbol().equals(sym)) {
//print i to show index number
//print objects[i].toString();
return true;
}
}
//print not found...
return false;

Implementing an Iterator for a Set, tracking the current element

How do you code an Iterator for a Set? Given that the iterator does not have access to the underlying data storage mechanism, and can only use the Set methods, is it possible to do this?
Every implementation I've managed to find creates the Iterator as an anonymous class; however, I am trying to figure out if there is a clever way to iterate over a Set while only accessing the methods provided by Set.
So far, the best I've managed to come up with looks like this:
import java.util.*;
public class SetIterator<E> implements Iterator
{
protected E[] arrayData;
protected Set<E> set;
protected int index;
protected boolean canRemove;
public SetIterator(Set<E> set)
{
this.set = set;
this.arrayData = (E[]) set.toArray();
this.index = -1;
this.canRemove = false;
}
public E next()
{
if(this.hasNext())
{
this.canRemove = true;
return this.arrayData[++this.index];
}
else
{
throw new NoSuchElementException("There is no next element");
}
}
public boolean hasNext()
{
return this.index + 1 < this.arrayData.length;
}
public void remove()
{
if(this.canRemove)
{
this.set.remove(this.arrayData[index--]);
this.arrayData = (E[]) this.set.toArray();
this.canRemove = false;
}
else
{
throw new IllegalStateException("Cannot remove element before calling next");
}
}
}
But that feels quite kludgy.... Is there a better way?
I think your title doesn't leave much space for answers, but if I use the following as your actual question:
How do you build an Iterator for a Set?
(and understand build as in get an instance of)
I think as PM 77-1 pointed out in the comments:
call the iterator() method on it, which it has since at least Java 1.5.
Keep in mind that it depends on the actual implementation of Set, wether the elements will always be iterated over in the same order.
if we look in AbstractCollection we will see that toArray actually calls the iterator() (abstract method) to produce the array which you will use, so your method still depends on the specific iterator, so you are essentially decorating the iterator.
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
Still not sure what you are trying to accomplish, the underlying datastructure of the set will have different (and specific) ways to efficently iterate the data, any generic solution would sacrafice performance, using the iterable interface should be generic enough.

Iterating through a collection

I am trying to create hasnext() has next() methods for a iterator so that the output of a collection will be:
"printing","elements","in","order","from","collection"
input:
[A] - ["printing", "elements", "in"]
[B] - ["order"]
[C] - ["from", "collection"]
At the moment I have my methods looking like:
public MyIterator(Collection<Collection<Object>> myColl) {
_myColl = myColl;
}
public boolean hasNext() {
if(myColl.next != null)
{
return true
}
return !queue.isEmpty();
}
public Object next() throws java.util.NoSuchElementException {
//Dont really know what to put in here....
}
Any pointers would be appreciated
The best way to do is declare a counter and increment when you are accessing the has next. In the logic if i will express, then that will be like this.
private int counter = 0;
public boolean hasNext(){
counter = counter < collection.size()? counter + 1: counter;// increment
return counter < collection.size();// check and give the appropriate boolean value
}
public T next(){
return collection.get(counter);// to get the counter number of element
}
where counter is the private variable in the class and T is the generic type on which type of object the collection is build up. like
Collection<String>
This answer is all about logic. it may or may not contain the exact code.
Well, i don't understand your question really.. why you can't just use the normal iterator?
I will say to you how to create a basic iterator, to let you understand how things works in basic then adapt your solution:
Suppose we need to iterate over a List<T> and you want to create an helper class to do it.
class ListIterator<T>
You need two private fields
The list to iterate
The pointers to the last item
and 3 methods + 1 constructor
hasNext() -> Boolean, returns true if there are more items to iterate
next() -> Return the next element in the list
reset() -> Reset the interal pointer
constructor -> Just takes as argument the list to iterate
How will look the fields?
private final List<T> list; // The list where this call will iterate
private int pointer; // The pointer to the next iterable item
As said in the description, the constructor will take the reference to the list so it will just be
public ListIterator(List<T> list)
{
this.list = list;
pointer = 0;
}
save the reference and set pointer to 0 (start).
Let's talk about the methods:
hasNext should check if our current pointer has reached the size of the list.
So it will just be (pointer != list.size())
public boolean hasNext()
{
return (pointer != list.size());
}
Will be true if more items are avaitable, false otherwise.
next return the next item if any. Could be simplified by using our hasNext method so it will be
public T next()
{
if (!hasNext())
throw new NoSuchElementException("no field");
return list.get(pointer++);
}
Things to notice:
T is the return because our list is type T
list.get(pointer++) we first get the item from the list in position pointer then we add 1 to the pointer
The reset method is just a pointer = 0.
public void reset()
{
pointer = 0;
}
How to use it?
Like other iterators, create a new object of type ListIterator and pass the list to iterate.
List<String> test = new ArrayList<String>();
test.add("Hello");
test.add("World");
test.add("Whatsapp");
ListIterator<String> iterator = new ListIterator<String>(test);
while (iterator.hasNext())
{
System.out.println(iterator.next());
}

Java: Retrieving an element from a HashSet

Why cannot I retrieve an element from a HashSet?
Consider my HashSet containing a list of MyHashObjects with their hashCode() and equals() methods overridden correctly. I was hoping to construct a MyHashObject myself, and set the relevant hash code properties to certain values.
I can query the HashSet to see if there "equivalent" objects in the set using the contains() method. So even though contains() returns true for the two objects, they may not be == true.
How come then there isn’t any get() method similar to how the contains() works?
What is the thinking behind this API decision?
If you know what element you want to retrieve, then you already have the element. The only question for a Set to answer, given an element, is whether it contains() it or not.
If you want to iterator over the elements, just use a Set.iterator().
It sounds like what you're trying to do is designate a canonical element for an equivalence class of elements. You can use a Map<MyObject,MyObject> to do this. See this Stack Overflow question or this one for a discussion.
If you are really determined to find an element that .equals() your original element with the constraint that you must use the HashSet, I think you're stuck with iterating over it and checking equals() yourself. The API doesn't let you grab something by its hash code. So you could do:
MyObject findIfPresent(MyObject source, HashSet<MyObject> set)
{
if (set.contains(source)) {
for (MyObject obj : set) {
if (obj.equals(source))
return obj;
}
}
return null;
}
It is brute-force and O(n) ugly, but if that's what you need to do...
You can use HashMap<MyHashObject, MyHashObject> instead of HashSet<MyHashObject>.
Calling containsKey() on your "reconstructed" MyHashObject will first hashCode() - check the collection, and if a duplicate hashcode is hit, finally equals() - check your "reconstructed" against the original, at which you can retrieve the original using get()
Complexity is O(1) but the downside is you will likely have to override both equals() and hashCode() methods.
It sounds like you're essentially trying to use the hash code as a key in a map (which is what HashSets do behind the scenes). You could just do it explicitly, by declaring HashMap<Integer, MyHashObject>.
There is no get for HashSets because typically the object you would supply to the get method as a parameter is the same object you would get back.
If you know the order of elements in your Set, you can retrieve them by converting the Set to an Array. Something like this:
Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();
The idea that you need to get the reference to the object that is contained inside a Set object is common. It can be archived by 2 ways:
Use HashSet as you wanted, then:
public Object getObjectReference(HashSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
for (Xobject o : set) {
if (obj.equals(o))
return o;
}
}
return null;
}
For this approach to work, you need to override both hashCode() and equals(Object o) methods
In the worst scenario we have O(n)
Second approach is to use TreeSet
public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) {
if (set.contains(obj)) {
return set.floor(obj);
}
return null;
}
This approach gives O(log(n)), more efficient.
You don't need to override hashCode for this approach but you have to implement Comparable interface. ( define function compareTo(Object o)).
One of the easiest ways is to convert to Array:
for(int i = 0; i < set.size(); i++) {
System.out.println(set.toArray()[i]);
}
If I know for sure in my application that the object is not used in search in any of the list or hash data structure and not used equals method elsewhere except the one used indirectly in hash data structure while adding. Is it advisable to update the existing object in set in equals method. Refer the below code. If I add the this bean to HashSet, I can do group aggregation on the matching object on key (id). By this way I am able to achieve aggregation functions such as sum, max, min, ... as well. If not advisable, please feel free to share me your thoughts.
public class MyBean {
String id,
name;
double amountSpent;
#Override
public int hashCode() {
return id.hashCode();
}
#Override
public boolean equals(Object obj) {
if(obj!=null && obj instanceof MyBean ) {
MyBean tmpObj = (MyBean) obj;
if(tmpObj.id!=null && tmpObj.id.equals(this.id)) {
tmpObj.amountSpent += this.amountSpent;
return true;
}
}
return false;
}
}
First of all, convert your set to an array. Then, get the item by indexing the array.
Set uniqueItem = new HashSet();
uniqueItem.add("0");
uniqueItem.add("1");
uniqueItem.add("0");
Object[] arrayItem = uniqueItem.toArray();
for(int i = 0; i < uniqueItem.size(); i++) {
System.out.println("Item " + i + " " + arrayItem[i].toString());
}
If you could use List as a data structure to store your data, instead of using Map to store the result in the value of the Map, you can use following snippet and store the result in the same object.
Here is a Node class:
private class Node {
public int row, col, distance;
public Node(int row, int col, int distance) {
this.row = row;
this.col = col;
this.distance = distance;
}
public boolean equals(Object o) {
return (o instanceof Node &&
row == ((Node) o).row &&
col == ((Node) o).col);
}
}
If you store your result in distance variable and the items in the list are checked based on their coordinates, you can use the following to change the distance to a new one with the help of lastIndexOf method as long as you only need to store one element for each data:
List<Node> nodeList;
nodeList = new ArrayList<>(Arrays.asList(new Node(1, 2, 1), new Node(3, 4, 5)));
Node tempNode = new Node(1, 2, 10);
if(nodeList.contains(tempNode))
nodeList.get(nodeList.lastIndexOf(tempNode)).distance += tempNode.distance;
It is basically reimplementing Set whose items can be accessed and changed.
If you want to have a reference to the real object using the same performance as HashSet, I think the best way is to use HashMap.
Example (in Kotlin, but similar in Java) of finding an object, changing some field in it if it exists, or adding it in case it doesn't exist:
val map = HashMap<DbData, DbData>()
val dbData = map[objectToFind]
if(dbData!=null){
++dbData.someIntField
}
else {
map[dbData] = dbData
}

Could anyone tell me why this returns an empty list (NPE)?

I have this code that is supposed to merge two instances of SortedLinkedList into one SLL (based on mergeSort merge), but is returning an empty list instead:
import java.util.LinkedList;
public class SortedLinkedList<T extends Comparable<? super T>>
extends LinkedList<T> {
private LinkedList<T> list; // the sorted list
// constructor, sorted with insertion sort
public SortedLinkedList(LinkedList<T> in)
{
if(in.peek() == null || in.size() == 1)
return;
else {
list = new LinkedList<T>();
for(T e : in)
list.add(e);
int i, j;
T temp;
for(i = 0; i < list.size(); i++){
j = i;
temp = list.get(j);
while(j > 0 && list.get(j-1).compareTo(temp) > 0){
list.set(j, list.get(j-1));
j--;
}
list.set(j, temp);
}
}
}
// return the union of the sorted linked lists this
// and other
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
list = new LinkedList<T>();
SortedLinkedList<T> temp = new SortedLinkedList<T>(list);
int i = 0, j = 0;
while(i < this.size() && j < other.size()){
if(this.get(i).compareTo(other.get(j)) <= 0){
temp.add(this.get(i));
i++;
}
else {
temp.add(other.get(j));
j++;
}
}
while(i < this.size()){
temp.add(this.get(i));
i++;
}
while(j < other.size()){
temp.add(other.get(j));
j++;
}
return temp;
}
// print the items in list
public void print()
{
for(T e : list)
System.out.println(e);
}
}
In the SLL constructor, I have it simply return on a null list (and the private variable, list, is initialized in the first line of this method). However from what I know, this should still give me an SLL object (initially also null). I can add to temp just fine in the method itself, but get a NullPointerException when printing the list.
I realize it's not very efficient to use get with LinkedList. I'll switch them with an iterator after I settle this.
Any hints would be quite appreciated.
EDIT: Interestingly, I get the same result if I put both lists in a temporary LL and then use the constructor on it. The types are compatible since SLL extends LL:
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
LinkedList<T> temp = new LinkedList<T>();
temp.addAll(this);
temp.addAll(other);
SortedLinkedList<T> merge = new SortedLinkedList(temp);
return merge;
}
EDIT2: It seems #Mead was correct... while size() and get() seem to work for the SLL, add() does not. I was thinking that since I'm extending LinkedList, it would work with the SLL as well. It didn't, and overriding them did nothing as well... I'm out of ideas for this. Suggestions?
Great! Your edit pretty much reveals your problem: you're not extending the LinkedList properly. Fix that, and then work on union.
The problem at hand: This is a class called SortedLinkedList. We can assume it's meant to be just like LinkedList, but the values in it are sorted. So, given that, this should work:
LinkedList<Integer> unsorted = new LinkedList<Integer>();
unsorted.add(200);
unsorted.add(100);
unsorted.add(300);
SortedLinkedList<Integer> sorted = new SortedLinkedList<Integer>(unsorted);
System.out.println(sorted.size());
for (Integer i : sorted) {
System.out.println(i);
}
// Should print out:
// 3
// 100
// 200
// 300
But it will not. Run your code, what does it print out?
Back? Why did it print out that? First, consider two variables you can use in the class's code: this refers to the SortedLinkedList object, and this.list refers to an instance variable inside that SortedLinkedList object. Then let's look at the constructor: when you add to the list, you're calling this.list.add(). What you have written makes SortedLinkedList a wrapper around the list instance variable - you're not adding to the SortedLinkedList (this) you are adding to a list inside that (this.list).
The only methods that use your this.list instance variable are the constructor, print, and makeUnion. All the other LinkedList methods aren't aware of the list variable, so when I call get():
LinkedList<Integer> unsorted = new LinkedList<Integer>();
unsorted.add(200);
unsorted.add(100);
unsorted.add(300);
SortedLinkedList<Integer> sorted = new SortedLinked<Integer>(unsorted);
System.out.println(sorted.get(0));
It doesn't know to look in your this.list variable, so it won't get 100 to print. In fact, it will crash because there is no value in index 0. You didn't add to the instance variables that get() actually uses, so the methods think that SortedLinkedList object is empty. this.list is a new variable that the inheritted methods don't know about.
So, if we examine your latest edit:
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
LinkedList<T> temp = new LinkedList<T>();
temp.addAll(this);
temp.addAll(other);
SortedLinkedList<T> merge = new SortedLinkedList(temp);
return merge;
}
temp.addAll(this) doesn't work, because all the methods of this think that the list is empty because they're not looking at this.list. temp.addAll(other) doesn't work either, for the same reason.
What is common when you extend classes is that you want the existing methods to continue working. This means that you need to store the data where get() and other methods expect it to be. How do you do that? Well, you're already doing it! You are already doing the right thing - but you are doing it on the instance variable this.list instead of this. Start calling this.add(), this.set(), this.size() instead of this.list.add() and remove the instance variable list completely - it's not needed, you have this. Then the data will be where the other methods expect it to be.
(And call super() on the first line of your constructor, so the code in the super class's constructor is called). Good luck on your homework - I'd recommend testing the object works as-is before adding new methods.
just curious after looking at the implementation, but couldn't you have just done a .addAll(...) followed by a Collections.sort(...)? That's what I would have preferred personally.

Categories