Call method through Arraylist of another class containing a HashMap - java

So I'm taking a basic course in Java at university. I'm trying to create a class Bachelorstudents containing an arraylist of class Bachelorstudent (respectively plural and singular of "bachelorstudents" in english) which contains a HashMap of course (key) and marks (value).
My problem is the infamous "non-static method cannot be referenced from a static context".
"Bachelorstudent"-class:
public class Bachelorstudent{
private String navn;
private int studentNummer;
private HashMap<String, Integer> karakterListe = new HashMap<>();
public Bachelorstudent(String navn, Integer studentNummer){
setNavn(navn);
setStudentNummer(studentNummer);
}
public Bachelorstudent(){
}
public void setKarakter(String fagkode, Integer karakter){
karakterListe.put(fagkode, karakter);
}
public HashMap<String, Integer> getKarakter(){
return karakterListe;
}
public int snitt(){
Integer snittKarakter = 0;
int counter = 0;
if(!karakterListe.isEmpty()){
for(Integer karakter : karakterListe.values()){
snittKarakter += karakter;
counter++;
}
}else{
return 6;
}
return snittKarakter /= counter;
}
public int getKarakterer(){
Integer karakterer = 0;
if(!karakterListe.isEmpty()){
for(Integer karakter : karakterListe.values()){
karakterer += karakter;
}
}else{
return 0;
}
return karakterer;
}
public void setNavn(String navn){
this.navn=navn;
}
public String getNavn(){
return navn;
}
public void setStudentNummer(int studentNummber){
this.studentNummer=studentNummer;
}
public int getStudentNummer(){
return studentNummer;
}
}
"Bachelorstudenter"-class:
public class Bachelorstudenter{
private ArrayList<Bachelorstudent> bachelorStudenter = new ArrayList<>();
public Bachelorstudenter(){
}
public void karakterSnitt(){
for(Bachelorstudent bachelorstudenter : bachelorStudenter){
Bachelorstudent student = new Bachelorstudent();
for(Bachelorstudent bachelorstudent : Bachelorstudent.getKarakter()){ //<-- Non-static method error.
}
}
}
public Boolean eksisterer(Bachelorstudent student){
boolean finnes = false;
for(Bachelorstudent bachelorstudent : bachelorStudenter){
if(bachelorstudent.getNavn().equals(student.getNavn())){
finnes = true;
}
}
return finnes;
}
public Boolean nyBachelorstudent(Bachelorstudent student){
if(!eksisterer(student)){
bachelorStudenter.add(student);
return true;
}
else{
System.out.println("Eksisterer i systemet fra før");
return false;
}
}
}
I have tried several things, such as calling an instance of class Bachelorstudent (as seen above), tried inheritance (not sure if I did this right, but what I did didn't work). How can I call on the .getKarakter() method in class Bachelorstudenter?
Edit: Just to clarify. The point of this method is to get the average of every mark of every bachelorstudent. I have a method in Bachelorstudent which does this, but I need the equivalent in Bachelorstudenter, which will find the average of every mark of every course of every student.

You need to use an object to call a non-static method.
In your example, you need to use the object of the current iteration to invoke the method:
for(Bachelorstudent bachelorstudenter : bachelorStudenter){ // Iterate over the bachelorStudenter list.
bachelorstudenter.getKarakter(); // Use the bachelorstudenter of this iteration.
}

Related

Hashmap method to sum

so i have the following task:
Given is the following class:
public class Konto {
private final String inhaber;
private double guthaben;
public Konto(String inhaber) {
this.inhaber = inhaber;
}
public String getInhaber() {
return inhaber;
}
public double getGuthaben() {
return guthaben;
}
public void einzahlen(double betrag) {
guthaben += betrag;
}
public void auszahlen(double betrag) {
guthaben -= betrag;
}
}
Using these classes, implement another class named Bank with the following properties:
The attribute named accounts is a directory of all
Account numbers and related accounts
(java.util.HashMap) and should be initialized in a default constructor of the class.
Write the addKonto method to add a new account of type Account, a getKonto method to query an account by its number, and a method called removeKonto that deletes an account with a specific number.
Implement a getGesamtguthaben method that returns the sum of the Balance(guthaben) of all bank accounts.
Write a containsKonto method that checks if an account with the given number exists in the bank and returns a corresponding Boolean value.
this is my code:
package Bank;
import java.util.HashMap;
import java.util.Map;
public class Bank {
private Map<String, Konto> konten;
public Bank() {
konten = new HashMap<String, Konto>();
}
public Konto addKonto(Konto konto) {
return konten.put(konto.getInhaber(), konto);
}
public String getKonto(String kontonr) {
if(konten.containsKey(kontonr)) {
return kontonr;
}
return null;
}
public Konto removeKonto(String kontonr) {
return konten.remove(kontonr);
}
public double getGesamtguthaben() {
for(double guthaben : konten) {
}
}
public boolean containsKonto(String kontonr) {
if(konten.containsKey(kontonr)) {
return true;
}else {
return false;
}
}
}
SO my question is how do i sum the balance of all Bank Accounts with a own method? And are the other methods correct? all help is appreciated
Use Map.entrySet to iterate over the entries.
double sum = 0;
for (Map.Entry<String, Konto> entrySet : konten.entrySet()) {
sum += entrySet.getValue().getGuthaben();
}
return sum;
Or using streams and Collectors.summarizingDouble
double sum = konten.entrySet()
.stream()
.collect(Collectors.summarizingDouble(entry -> entry.getValue().getGuthaben()))
.getSum();
Yes like user7 said. But instead of using the entrySet() you could also use the values() method.
double sum = konten.values()
.stream()
.collect(Collectors.summarizingDouble(konto-> konto.getGuthaben()))
.getSum();

Is it possible to avoid duplicate code when implementing methods for two similar class?

I have two classes: Fish and Plant. They do not inherit from any classes.
But both of them have one method called isAlive() which have the same implementation details. Now I have a list of fish and another list of dog and I need to remove dead fish and dead dog. I want my method to have same name but it is not possible without adding additional field to method signature. Is it possible I do not need to write additional chunk of code which does the same as the last chunk of code?
Below is the code. For class Model, Fish and Plant are two data members and they are ArrayList of Fish and Plant objects.
Is there any way I can write only one method called count and I do not need to add additional field to my method signature or modify my return type?
public class Fish{
public boolean isAlive(){
if(this.size > 0){
return true;
}
return false;
}
}
public class Plant{
public boolean isAlive(){
if(this.size > 0){
return true;
}
return false;
}
}
public class Model{
private int countDeadFish() {
int totalCount = 0;
for(Fish aFish : this.fish) {
if(aFish.isAlive() == false) {
totalCount += 1;
}
}
return totalCount;
}
private int countDeadPlants() {
int totalCount = 0;
for(Plant plant : this.plants) {
if(plant.isAlive() == false) {
totalCount += 1;
}
}
return totalCount;
}
}
If you do not want to use inheritance, then you can use a common method:
public class AliveChecker {
public static boolean isAlive(int size) {
return size > 0;
}
}
public class Plant{
public boolean isAlive(){
return AliveChecker.isAlive(this.size);
}
}
public class Fish{
public boolean isAlive(){
return AliveChecker.isAlive(this.size);
}
}
Since Fishand Plant do not inherit from anything yet you can consider creating a superclass and extend from it:
public class LivingThing {
protected int size = 1;
public boolean isAlive() {
return size > 0;
}
}
public class Plant extends LivingThing {
}
public class Fish extends LivingThing {
}
This example uses inheritance to classify Plantand Fish into the superclass LivingThing. You can set the size for example in the constructor of the Plant or an instance method:
public class Plant extends LivingThing {
public Plant(int size){
this.size = size;
}
}
Your Model could then be:
public class Model{
private int countDeadFish() {
return countDead(this.fish);
}
private int countDeadPlants() {
return countDead(this.plants);
}
private int countDead(ArrayList<LivingThing> things) {
int totalCount = 0;
for(LivingThing thing: things) {
if(!thing.isAlive()) {
totalCount++;
}
}
return totalCount;
}
}
Use interface
public interface LiveObject {
boolean isAlive();
}
public class Fish implements LiveObject {
public boolean isAlive(){
if(this.size > 0){
return true;
}
return false;
}
}
public class Plant implements LiveObject {
public boolean isAlive(){
if(this.size > 0){
return true;
}
return false;
}
}
public class Model{
private int countDead(Collection<LiveObject> objects) {
int totalCount = 0;
for(LiveObject obj : objects) {
if(obj.isAlive() == false) {
totalCount += 1;
}
}
return totalCount;
}
private int countDeadFish() {
return countDead(this.fish);
}
}
Based on the comments it seems you can't modify Fish or Plant. Here's an approach to reduce duplication in countDead<Something> methods which does not require this.
Basically you want to count items in an array which satisfy certain criteria. With Java 8 you can capture this criteria in a predicate using lambdas or method references. You do not need inheritance or implementation of a certain interface for this.
private long countDeadFish() {
return countDeadItems(this.fish, Fish::isAlive);
}
private long countDeadPlants() {
return countDeadItems(this.plants, Plant::isAlive);
}
private <T> long countDeadItems(Collection<T> items, Predicate<? super T> isAlive) {
return items.stream().filter(isAlive.negate()).count();
}
You could create a utility method (in a utility class somewhere):
public final class Liveliness {
private Liveliness() {
}
public static boolean isAlive(final IntSupplier sizer) {
return sizer.getAsInt() > 0;
}
}
Your method then becomes:
public boolean isAlive(){
return Liveliness.isAlive(this::getSize);
}
Alternatively, use an interface Life:
public interface Life {
int getSize();
default boolean isAlive(){
return getSize() > 0;
}
}
This way, adding a getSize method and inheriting from Life will add the method.
Note, avoid the following antipattern:
if(test) {
return true;
} else {
return false;
}
Use return test.

Returning arraylist error

I've been trying to create a class which determines if a set of integers within an arraylist is a subset of another arraylist.
However, I receive an "error: incompatible types: ArrayList cannot be converted to int" whenever I try to compile and it appears that "return members" is causing it.
Could someone tell me what is wrong with "return members"? Any help would be greatly appreciated.
// Define the Set class
import java.util.ArrayList;
class Set {
private ArrayList<Integer> members;
public Set()
{
members = new ArrayList<Integer>();
}
public int getMembers()
{
return members;
}
public void setMembers()
{
this.members = members;
}
// toString() method
public String toString()
{
return "Set A is a subset of set B.";
}
// Return true if 'this' is a subset of 'set',
// otherwise return false.
public boolean isSubset(Set set)
{
for(int i = 0; i < this.members.size(); i++)
if(!members.contains(this.members.get(i)))
return false;
return true;
}
}
This method is your issue:
public int getMembers()
{
return members;
}
Wrong return type, change it to:
public ArrayList<Integer> getMembers()
{
return members;
}
Also your setMembers() does not do anything, set's itself to itself. It should be changed to:
public void setMembers(ArrayList<Integer> newMembers)
{
this.members = newMembers;
}
you are making mistake in first place.change return type in getMenbers(). you are returning an Object type and you specified it to return an int(primitive).
a typical method can only return the specified type. hope it helps

Overriding value in heap java programming

I've added to my project a new data structure Heap<Integer,Integer> but the only problem I've got is that it prints me only one time the result.
If I have the input:
v=10;new(v,20);new(a,22);print(v)
at the end of execution
Heap={1->20, 2->22},
SymTable={v->1, a->2}
But what it gives me:
Heap: 1->22
SymTable: a -> 1
v -> 1
It overrides the first value.Here is the code from the controller where is the main part:
HeapAllocation crtStmt1=(HeapAllocation) crtStmt;
String varI = crtStmt1.getVarname();
Exp e = crtStmt1.getExpression();
int i=0;
Id<Object,Integer> tbl = state.getDict();
IHeap<Integer,Integer> heap1 = state.getHeap();
int value= e.eval(tbl, heap1);
heap1.put(++i, value);
if (tbl.containsKey(varI))
tbl.update(varI,i);
tbl.update(varI, i);
The problem I guess is after this line:
heap1.put(++i, value);
because for a new operation it doesn't append to the previous one, just overrides it.
Edit:
The implementation of the heap:
public class Heap<Integer,In> implements IHeap<Integer, Integer>,Serializable{
private Map<Integer, Integer> mapp;
public Heap(){
mapp = new HashMap<Integer,Integer>();
}
public void put(Integer index, Integer value){
mapp.put(index, value);
}
public void remove(Integer index){
try{
if(isEmpty())
throw new ExceptionRepo();
else
mapp.remove(index);
}catch (ExceptionRepo ex){
System.err.println("Error: Heap is empty.");
}
}
public boolean isEmpty(){
return mapp.isEmpty();
}
public Integer get(Integer index){
return mapp.get(index);
}
public boolean containsIndex(Integer index){
return mapp.containsKey(index);
}
public void update(Integer index, Integer value){
mapp.put(index, value);
}
public String toString(){
Set<Integer> all = mapp.keySet();
Object[] keysA= all.toArray();
String res="";
for(int i=0; i<mapp.size(); i++){
Integer v = mapp.get(keysA[i]);
res += keysA[i].toString() + "->" + v.toString() + "\r\n";
}
return res;
}
}
Edit2: Maybe the problem is in the eval function implementation.To be clear, I have a Exp class:
public class Exp{
public int eval(Id<Object,Integer> tbl)throws ExceptionRepo{
return 0;
}
public String toString(){
return "";
}
public int eval(Id<Object,Integer> tbl,IHeap<Integer,Integer> heap) throws ExceptionRepo{
return 0;
}
And some derived classes that extends the Exp class.I added a new method in the ConstExp class:
public class ConstExp extends Exp implements Serializable{
int number;
public int eval(Id<Object,Integer> tbl) throws ExceptionRepo{
return number;
}
public ConstExp(int n){
number = n;
}
public String toString(){
return "" + number;
}
public int eval(Id<Object,Integer> tbl,IHeap<Integer,Integer> heap) throws ExceptionRepo{
return number; //THIS IS THE NEW METHOD
}
This class should return a value..so for "v=20", after execution of the statement it puts the value 20 in the v based on this class implementation.
If it's useful this is the statement evaluation rule for the heap(that I implemented in the controller up there):
Stack1={new(var,exp)| Stmt2|...}
SymTable1
Heap1
==>
Stack2={Stmt2|...}
let be v=eval(exp,SymTable1,Heap1) in
Heap2 = Heap1 U {newfreelocation ->v}
if var exists in SymTable1 then SymTable2 = update(SymTable1,
var,newfreelocation)
else SymTable2 = add(SymTable1,var, newfreelocation)
How to resolve this?

How to get value of variable from other class?

I have a public integer variable (MainReg) in my Counter Class. I want to get value of this variable and set it in my JComponent class. Here is piece of my JComponent class:
public class Komponent2 extends JComponent implements ActionListener
{
Counter counter3;
.
.
.
int a = counter3.valueOf(MainReg);
But it doesn't work. I tried also:
int a = valueOf(counter3.MainReg);
int a = counter3.valueOf(counter3.MainReg);
int a = counter3.MainReg;
But it still doesn't work. How can I get this variable? Thanks for helping me.
EDIT
Here is my Counter class:
import java.util.Observable ;
public class Counter extends Observable
{
public int MainReg;
public int CompareReg;
public Mode countMode;
public boolean OVF;
private int a=0;
public Counter()
{
OVF=false;
}
public void setCompareReg(int dana)
{
CompareReg=dana;
}
public void setMainReg(int dana2)
{
MainReg=dana2;
}
public void setMode(Mode countMode)
{
this.countMode=countMode;
}
public void Count()
{
if (countMode==Mode.UP)
{
MainReg++;
OVF=false;
if (CompareReg < MainReg)
{
OVF=true;
MainReg=0;
setChanged();
notifyObservers();
}
}
else if (countMode==Mode.UPDOWN)
{
if(MainReg >= CompareReg)
{
a=MainReg;
MainReg--;
OVF=true;
}
else
{
if(MainReg >= a)
{
MainReg++;
OVF=false;
}
else
{
MainReg--;
if(MainReg==0)
{
a=0;
}
OVF=false;
}
}
}
else if (countMode==Mode.CONTINOUS)
{
MainReg++;
OVF=false;
if (65536 < MainReg)
{
MainReg=0;
OVF=true;
}
}
}
}
Well I see two ways you can do this.
Your MainReg integer is public, you could simply use int i = counter3.MainReg;
Or you could create a getMainReg() method in your Counter class. Then call it from whatever class.
EX:
public int getMainReg() {
return this.MainReg;
}
Give your Counter class getter methods, and then call them when you need to access their values. i.e.,
public int getMainReg() {
return mainReg;
}
public int getCompareReg(){
return compareReg;
}
public Mode getCountMode() {
return countMode;
}
And make your fields all private. Also your code should obey Java naming rules: variable names should begin with lower-case letters.
Also be sure that you've initialized your counter variable in the class that uses it, either by creating a new instance, or if appropriate, passing in a valid instance in a constructor or method parameter.

Categories