java.util.LinkedList<ClassName> cannot be converted to ClassName - java

I am on my way to learning java, so please bear with me on this one, even if its very simple to you.
I'm working with two LinkedLists:
private LinkedList<BloodDonor> x;
private LinkedList<BloodDonor> y;
public List()
{
x = new LinkedList<>();
y = new LinkedList<>();
}
I have a method called heroDonors that searches the LinkedList x to see if there are any people who donated blood more than 50 times. If so, that donor gets added to LinkedList y and removed from LinkList x. If no donors who donated more than 50 times are present, an empty LinkedList of y is returned.
I need the LinkedList y to be returned by the method, but I get the error java.util.LinkedList<BloodDonor> cannot be converted to BloodDonor.
public BloodDonor heroDonors()
{
int donations = 50;
for (BloodDonor donor : x) {
int number = donor.getNumberOfDonations();
if (donations < number) {
y.add(donor);
x.remove(donor);
}
if (donations > number) {
}
}
return y;
}
Could anyone explain why I am getting this error?

If you want to return a List of BloodDonors you have to actually make your method of that type:
public LinkedList<BloodDonor> heroDonors() {
LinkedList<BloodDonor> result = new LinkedList<>();
...
return result;
}
BTW: I think in this case you should not use a field y but declare a local variable on order to avoid side effects. You might also consider returning the base type List<BloodDonor> instead, this will better allow to use another collection if needed (and I would never call a application class List).

Change
public BloodDonor heroDonors()
to
public List<BloodDonor> heroDonors()

Related

Reversing an ArrayList (Understanding the code)

I found an exercise in a book that adds some money into an ArrayList, and then reverses them. I know we can easily use Collection.reverse(), which is what my textbook shows, but I found another cool solution online that I am trying to understand but having trouble with.
Heres the code:
class Purse {
private ArrayList<String> coins = new ArrayList<String>();
public void addCoin(String coinName) {
coins.add(coinName);
}
public void reverse() {
for(int start = 0, end = coins.size() - 1; start < coins.size() / 2; start++, end--) {
swap(start,end,coins);
}
}
private void swap(int starting, int ending, List aList) {
Object temp = aList.set(starting, aList.get(ending));
aList.set(ending,temp);
}
public String toString() {
return "Purse: " + coins;
}
}
public class PurseDemo {
public static void main(String [] args) {
Purse purseObj = new Purse();
purseObj.addCoin("Quarter");
purseObj.addCoin("Dime");
purseObj.addCoin("Penny");
purseObj.addCoin("Nickel");
System.out.println(purseObj);
purseObj.reverse();
System.out.println(purseObj);
}
}
Here is where my confusion is:
Object temp = aList.set(starting,aList.get(ending));
aList.set(ending,temp);
First of all, I think I get the idea of this. However, this is my first time seeing the Object keyword. What I don't really get is what temp actually represents ( I got this code off online, in my book they havent introduced this keyword Object yet)
Here are my thoughts on an example iteration
Suppose our arrayList has
[Quarter,Dime,Penny,Nickel]
According to Object temp = aList.set(starting,aList.get(ending));
We take the the first spot in the ArrayList Quarter and put the value of nickel in there. So we get the ArrayList
[Nickel,Dime,Penny,Nickel]
Now I'm kind of confused.. When I system.out.println(temp), it tells me the values are Quarter and Dime. But why? Can someone go through an example iteration with me?
AFTER READING ANSWER
[Quarter,Dime,Penny,Nickel]
Nickel replaces Quarter, thus temp is Quarter. So we add Quarter to the end
I.E we get
Quarter,Dime,Penny,Quarter
Wait.. But where did our nickel go?!
The set() method returns the object that is being displaced by the new object. The first line
Object temp = aList.set(starting,aList.get(ending));
is the same as:
Object temp = aList.get(starting);
aList.set(starting, aList.get(ending));
You could actually do it without the temp variable, in one line:
aList.set(ending, aList.set(starting, aList.get(ending)));
The swap method can be translated into its "usual form":
Object temp = aList.get(starting);
aList.set(starting, aList.get(ending));
aList.set(ending, temp);
All the code you found does is combine the first two lines because List.set promises to return the replaced value.
Now let's see your example, where aList initially is [Quarter,Dime,Penny,Nickel], and starting is 0 and ending is 3.
Object temp = aList.get(starting);, now temp is Quarter.
aList.set(starting, aList.get(ending));, now aList is [Nickel,Dime,Penny,Nickel].
At last, aList.set(ending, temp);, sets the last element of aList to Quarter: [Nickel,Dime,Penny,Quarter]

Checking if there is a certain string in an object contained in an ArrayList, then adding the object to another ArrayList

I have Arraylist of objects ArrayList<Product> productDatabase. The object contains a String and a double and then these objects will be added to the productDatabase by addProductToDatabase(); as follows:
public void addProductToDatabase(String productName, double dimensions); {
Product newProduct = new Product(ProductName, dimensions);
productDatabase.add(newProduct);
}
I also want to make an Arraylist<ProductCount> productInventory which counts how many Product are accounted for. Before it can add to ArrayList<ProductCount> productInventory however, it should first check if the object details exist in the productDatabase while running addProductToInventory()
public Product getProduct(String name) {
for(i = 0; i < productDatabase.size(); i++)
if(productDatabase.get(i).contains(name) //Error: cannot find symbol- method contains.(java.lang.String)
return productDatabase.get(i)
}
public void addProductToInventory(String productName, double quantity)
{
Product p = getProduct(name);
productCount.add(new ProductCount(o, quantity));
}
Assume that you always have different objects (so nothing will have the same name), but you're always unsure of the dimensions (so when you input the same producttName + dimensions you edit the dimensions in it).
At the end of the day, you have to put all the items in it a large box and report what you've inventoried, so you also have a getProductQuantityTotal() and you have to getProductDimensionTotal()-- as the name suggests, get the total of number of objects you've counted, and the sum of the dimensions.
What do I have to add/change/remove about this code? Don't consider syntax first (because BlueJ checks for common syntax errors and I just typed this by hand). I'm sure that I'm missing a for statement somewhere, and I'm probably misusing contains() because it won't recognise it (I have import java.util.*; and import java.util.ArrayList;)
To answer the question in your post title: How to find a string in an object, for a list of those objects, here is some sample code that does this:
First, I created a trivial object that has a string field:
class ObjectWithStringField {
private final String s;
public ObjectWithStringField(String s) {
this.s = s;
}
public String getString() {
return s;
}
}
And then a code that populates a list of it, and then searches each for the string. There's no magic here, it just iterates through the list until a match is found.
import java.util.List;
import java.util.Arrays;
/**
<P>{#code java StringInObjectInList}</P>
**/
public class StringInObjectInList {
public static final void main(String[] ignored) {
ObjectWithStringField[] owStrArr = new ObjectWithStringField[] {
new ObjectWithStringField("abc"),
new ObjectWithStringField("def"),
new ObjectWithStringField("ghi")};
//Yes this is a List instead of an ArrayList, but you can easily
//change this to work with an ArrayList. I'll leave that to you :)
List<ObjectWithStringField> objWStrList = Arrays.asList(owStrArr);
System.out.println("abc? " + doesStringInObjExistInList("abc", objWStrList));
System.out.println("abcd? " + doesStringInObjExistInList("abcd", objWStrList));
}
private static final boolean doesStringInObjExistInList(String str_toFind, List<ObjectWithStringField> owStrList_toSearch) {
for(ObjectWithStringField owStr : owStrList_toSearch) {
if(owStr.getString().equals(str_toFind)) {
return true;
}
}
return false;
}
}
Output:
[C:\java_code\]java StringInObjectInList
abc? true
abcd? false
In the real world, instead of a List, I'd use a Map<String,ObjectWithStringField>, where the key is that field. Then it'd be as simple as themap.containsKey("abc");. But here it is implemented as you require. You'll still have quite a bit of work to do, to get this working as specifically required by your assignment, but it should get you off to a good start. Good luck!

Why another branch is unreachable in my code?

Why the output of the following code is always suck. How to get happy as the output? Why the happy branch is unreachable?
public class HowToMakeStackoverflowBetter {
private static final int HUMAN_PATIENCE = 10;
private List<Member> members = new ArrayList<>();
private int atmosphere = -10;
private Random r = new Random();
public HowToMakeStackoverflowBetter(int size) {
for (int i = 0; i < size; i++) { members.add(new Member()); }
}
public Member pick() { return members.get(r.nextInt(members.size())); }
public class Member {
private int patience = HUMAN_PATIENCE;
private Question question = null;
public Member() { patience = r.nextInt(patience+1) + atmosphere; }
public void vote(Question q) {
if (patience >= 0) {
voteUp(q);
} else {
voteDown(q);
}
}
public void ask() {
question = new Question();
for (Member member : members) {
member.vote(question);
}
}
private void voteUp(Question q) { ++q.vote; }
private void voteDown(Question q) { --q.vote; }
public String toString() {
return (question.vote >= 0)? "Happy!" : "Suck!";
}
}
public class Question { private int vote; }
public static void main(String[] args) {
HowToMakeStackoverflowBetter stackoverflow = new HowToMakeStackoverflowBetter(100);
Member me = stackoverflow.pick();
me.ask();
System.out.println(me);
}
}
After a 1000 times loop, it gives us 1000 sucks. I remember 2 or 3 years ago, this was not the case. Something changed.
Two problems. First:
linkedList::linkedList(){
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel.str="I am sentinel!!";
};
sentinel is your member variable, and .last is its pointer to another node. This hasn't been initialised, so trying to use it is undefined behaviour. In practice, it's effectively pointing at a random address in (or out of) memory, and you attempt to dereference the pointer then copy the entire sentinel object over the node at the imagined pointed-to address: i.e. you try to copy the 3 pointers in the sentinel node member variable to a random address in memory.
You probably want to do this:
linkedList::linkedList()
{
sentinel.last = &sentinel;
sentinel.next = &sentinel;
sentinel.str = "I am sentinel!!";
}
Secondly, you explicitly call the destructor for linkedList, which results in undefined behaviour when the compiler-arranged destruction is performed as the object leaves the stack scope it's created in - i.e. at the end of main().
I suggest you change node.str to be a std::string, as in any realistic program you'll want to be able to handle variable text, and not just point to (constant) string literals. As is, if you mix string literals and free-store allocated character arrays, you'll have trouble knowing when to call delete[] to release the memory. You could resolve this by always making a new copy of the string data to be stored with new[], but it's safer and easier to use std::string.
Since you allocated it as a local variable, your mylist will be destroyed automatically upon exiting main. Since you've already explicitly invoked its destructor, that leads to undefined behavior (attempting to destroy the same object twice).
As a quick guideline, essentially the only time you explicitly invoke a destructor is in conjunction with placement new. If you don't know what that is (yet), that's fine; just take it as a sign that you shouldn't be invoking destructors.
You forgot to initialize sentinel
In code below you are trying to initialize sentinel (which is not yet constructed) with sentinel(same thing). So you have to pass something to constructor which can be used to initialize your member variable sentinel
*sentinel.last=sentinel;
Also no need to call destructor like this. Destructor will be called once your myList goes out of scope.
myList.~linkedList();
the program may crash, with this:
*sentinel.last=sentinel;
*sentinel.next=sentinel;
sentinel is not initialized sot i has random value on stack.
You're trying to de-reference the pointers last and next of member variable sentinel when they are not yet initialized.
And these de-references *sentinel.last=sentinel *sentinel.next=sentinel are causing the crash because without assigning the values to pointers you're changing the value pointed by the pointers.
You can do like this
sentinel.last=&sentinel;
sentinel.next=&sentinel;
And as pointed out by other explicit destructor calls aren't need here.

How to use a method from a generic object list iterator to call another class' equals method

I am taking an intro to Java course, and we are learning about how to make a generic object list iterator (I call it List) that can be extended into more specific lists later. This way, if I decide to make another list class later on, I can just extend List instead of going through typing all the getters, setters, insert(), delete(), etc. again.
My professor wants our List class to have an isThere() method. She wants it to accept an object, iterate through the list until it finds a match, and then return the index of where it found it. I have searched for similar questions on this site, but most of the methods suggested include "<>", or hash which we are not allowed to use in this class. We are also not allowed to use any Array method that java provides for us. We must write our own methods.
So, my problem is that I have stored 10 Users in my Object List. I intentionally stored one element as "Bimmy" so that I could try to find that element using my isThere() method. When I went through debug mode, it shows that it reaches the User method equals() and then returns false. Debug also shows that the User's names are both "Bimmy" and the id values are also the same (Users having the same name and id are the requirements for the equals method to return true).
Again, this is my first semester taking Java, and I think my problem has to do with casting. I think that in the List's isThere(), "list[i]" doesn't know that it is a User, or that it should compare itself to the other User object. However, I am really not sure. If anyone would be so kind as to help, I would greatly appreciate it. I will post the code below...
List isThere() method:
public int isThere(Object obj)
{
for(int i = 0; i<index; i++)
{
if(list[i].equals(obj))
{
return i;
}
}
return -1;
}
The User's equal() method:
public boolean equals(User user)
{
if(user.getName().equals(name) && user.getId().equals(id))
{
return true;
}
else
return false;
}
This is what I am doing in Main:
System.out.println("-----------------------------test isThere()");
UserList check = new UserList(10);
check.tryAdd(new User("Jimmy", "562801"));//I am adding 10 Users here.
check.tryAdd(new User("Jimmy", "562801"));//I put one as "Bimmy" so that I can
check.tryAdd(new User("Jimmy", "562801"));//test this method to find that User
check.tryAdd(new User("Jimmy", "562801"));//at index 8
check.tryAdd(new User("Jimmy", "562801"));
check.tryAdd(new User("Jimmy", "562801"));
check.tryAdd(new User("Jimmy", "562801"));
check.tryAdd(new User("Jimmy", "562801"));
check.tryAdd(new User("Bimmy", "562801"));
check.tryAdd(new User("Jimmy", "562801"));
System.out.println(check.toString());
System.out.println(check.isThere( new User("Bimmy","562801")));
At this point the console outputs -1 meaning "Bimmy" was not found. I am not sure how to fix this problem, but I am looking forward to learning what I have done wrong.
This is more about my list:
protected final int MAXSIZE=10;
protected Object [] list;
protected int index;
protected int curPos;
public List()
{
list = new Object[MAXSIZE];
for(int i = 0;i<MAXSIZE; i++)
{
list[i]=new Object();
}
index = 0;
curPos = 0;
}
public List(int size)
{
list = new Object[size];
for(int i = 0;i<size; i++)
{
list[i]=new Object();
}
index = 0;
curPos = 0;
}
adding elements
public void tryAdd(Object thing)//adds Object to index, increment index. if full, it deques first
{
if(isFull())
{
deque();
setElement(thing,index-1);
}
else
{
setElement(thing,index);
index++;
}
}
public void setElement(Object setWhat, int which) //assigns a specific element with the parameters
{
list[which] = setWhat;
}
Also UserList:
public UserList(int size){super(size);}
I believe it's calling the Object.equals method (which actually just checks if they're the exact same object) (every object is a subclass of Object).
This is because you're calling
list[i].equals(obj)
where obj is of type Object (even though it's actual type is User).
Having your equals method override Object.equals should work:
#Override
public boolean equals(Object other)
{
User user = (User)other;
if(user.getName().equals(name) && user.getId().equals(id))
return true;
else
return false;
}
An alternative that should work is changing the type of the input parameter of isThere to User.

Java bug or feature?

Ok, here is the code and then the discussion follows:
public class FlatArrayList {
private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] currentRow = new int[10];
int counter = 0;
while (true) {
for (int i = 0; i < 10; i++) {
currentRow[i] = probModel.size();
}
TestWrapperObject currentWO = new TestWrapperObject(currentRow);
probModel.add(counter, currentWO);
TestWrapperObject testWO = probModel.get(counter);
// System.out.println(testWO);
counter++;
if (probModel.size() == 10) break;
}
// Output the whole ArrayList
for (TestWrapperObject wo:probModel) {
int [] currentTestRow = wo.getCurrentRow();
}
}
}
public class TestWrapperObject {
private int [] currentRow;
public void setCurrentRow(int [] currentRow) {
this.currentRow = currentRow;
}
public int [] getCurrentRow() {
return this.currentRow;
}
public TestWrapperObject(int [] currentRow) {
this.currentRow = currentRow;
}
}
What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop,
the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.
You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.
Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.
i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book
select isn't broken
it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)

Categories

Resources