I'm completing an exercise which asks me to write a method called totalTax, which takes as parameters two ArrayLists, one containing houses, the other containing shops, and returns the total tax payable on all those properties. Shop, and House are two classes in my program. Each has a method which returns tax as an integer.
My solution is as follows, but I'm not sure it's the most efficient way of doing it, due to the repetition, and it doesn't compile! Is there a way to achieve the same thing, but avoid duplicate code such as I have below?
private int totalTax(ArrayList<Shop> list1, ArrayList<House> list2) {
int total;
for (int a =0; a <= list1.size() -1; a++) {
total += list1.shopTax();
}
for (int a = 0; a<= list2.size() -1; a++) {
total += list2.houseTax();
}
return total;
}
Your solution won't work since you have to access to the elements in the List, you're retrieving the tax from the list directly, as shown here:
total += list1.shopTax();
It should be
total += list1.get(a).shopTax();
Similar here:
total += list2.houseTax();
It should be:
total += list2.get(a).houseTax();
Still, this approach is using your ArrayList as a wrapper for an array. Another alternative could be treating the ArrayList as a List, so you will use Iterator rather than accessing the elements through get method. There are two ways to use Iterator:
Declaring the Iterator and initializing it with List#iterator:
Iterator<Shop> shopIterator = list1.iterator();
while (shopIterator.hasNext()) {
Shop shop = shopIterator.next();
total += shop.shopTax();
}
Iterator<House> houseIterator = list2.iterator();
while (houseIterator.hasNext()) {
House house = houseIterator.next();
total += house.shopTax();
}
Using enhanced for loop:
for (Shop shop : list1) {
total += shop.shopTax();
}
for (House house : list2) {
total += house.houseTax();
}
In terms of DRY code, you can do better if you alter your class hierarchy such that House and Shop both implement a shared interface. Consider the following:
public interface Taxable{
public int getTax();
}
public class House implements Taxable{
//Other code you've written for House
public int getTax(){
return houseTax();
}
}
public class Shop implements Taxable{
//Other code you've written for Shop
public int getTax(){
return shopTax();
}
}
From there you can take in a single ArrayList of Taxables (containing both houses and shops) and total their taxes without repeating yourself.
private int totalTax(ArrayList<? extends Taxable> lst) {
int total;
for (Taxable t : lst) {
total += t.getTax();
}
return total;
}
If you absolutely must take two ArrayLists as parameters, you can still not repeat yourself creating this method, relying on the above method as its helper.
private int totalTax(ArrayList<House> list1, ArrayList<Shop> list2){
return totalTax(list1) + totalTax(list2)
}
To answer the specific problems with the code not compiling
See comments below:
class Shop {
int tax;
int shopTax() { return tax; }
}
class House {
int tax;
int houseTax() { return tax; }
}
private int totalTax(ArrayList<Shop> list1, ArrayList<House> list2) {
// Need to initialize total to 0
int total = 0;
for (int a =0; a <= list1.size() -1; a++) {
// Need to get the element from the list first
Shop shop = list1.get(a);
total += shop.shopTax();
}
for (int a = 0; a<= list2.size() -1; a++) {
// Need to get the element from the list first
House house = list2.get(a);
total += house.houseTax();
}
return total;
}
To answer "Is there a way to achieve the same thing, but avoid duplicate code such as I have below?"
interface Taxable {
double getTax();
}
class Shop implements Taxable {
public double getTax() {
return 0d;
}
}
class House implements Taxable {
public double getTax() {
return 0d;
}
}
public double totalTax(List<Taxable> thingsToTax) {
double total = 0;
for (Taxable taxable : thingsToTax) {
total += taxable.getTax();
}
return total;
}
Updated
I missed the part where 'the method must take two parameters'. So adding this part:
public double totalTax(List<Taxable> thingsToTax, List<Taxable> otherThingsToTax) {
return totalTax(thingsToTax) + totalTax(otherThingsToTax);
}
This also uses double instead of int which I have to imagine is more appropriate. Otherwise, feel free to use int if still desired.
Something like this is little bit efficient :
private int totalTax(ArrayList<Shop> list1, ArrayList<House> list2) {
int total = 0;
int miSize = Math.min(list1.size(), list2.size());
for (int a = 0; a < minSize; a++)
total += list1.get(a).shopTax() + list2.get(a).houseTax();
if(list1.size() > minSize)
for (int a = minSize; a < list1.size(); a++)
total += list1.get(a).shopTax();
else
for (int a = minSize; a < list2.size(); a++)
total += list2.get(a).shopTax();
return total;
}
Related
I'm doing something that produces the right result. However, it is wrong from a design POV.
The point of the program is to list the result of all the powers of a number up to and including the user-defined limit.
I have a constructor which accepts the base and the exponent from the Scanner. Then a method, which utilises a for loop to calculate the power for each exponent.
Now, the problem is that I'm printing the result from each loop iteration directly from this method. This beats the point of private variables and it being void in the 1st place.
Therefore, I want to define a getter method which returns the result of each power to the output. I used to set them just fine for if/switch statements, but I don't know how to do the same for loops. If I assign the result to a variable within the loop and return that variable from the getter then it will return only the output from the final iteration.
Private implementation
package Chapter6Review;
public class Powers {
private int target;
private int power;
public Powers(int target, int power) {
this.target = target;
this.power = power;
}
public void calculatePower() {
for (int i = 0; i <= power; i++) {
System.out.println((int) Math.pow(target, i));
}
}
/*
public int getPower() {
return
}
*/
}
User interface
package Chapter6Review;
import java.util.Scanner;
public class PowersTester {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter your base: ");
int target = in.nextInt();
System.out.print("Enter your exponent: ");
int power = in.nextInt();
Powers tester = new Powers(target, power);
tester.calculatePower();
}
}
You can simply use a List ;
public List<Integer> calculatePower() {
int p;
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i <= power; i++) {
p = (int) Math.pow(target, i);
result.add(p);
}
return result;
}
Then in you main method, you can iterate the list to print the powers like that :
List<Integer> result = new ArrayList<Integer>();
Powers tester = new Powers(target, power);
result = tester.calculatePower();
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
You could store each of the results in a List:
List<Power> list = new ArrayList<>();
and when you call it add it as well
list.add(new Powers(target, power));
At the end you can iterate over the list like this:
for (Power power : list){
// your code
}
You might consider using streams as well
public List<Integer> calculatePower() {
return IntStream
.rangeClosed(0, power). // iterate from 0 till power inclusive
.mapToObj(i -> (int) Math.pow(target,i))
.collect(Collectors.toList()); // get result as list
}
Thanks for all the answers. Using a list seems to be a good choice.
Since I haven't covered lists yet, I resorted to this solution for now. But I don't like having code that can affect the solution in the main. Ideally, the loop should go in the private implementation.
Main
Powers tester = new Powers(target, power);
for (int i = 0; i <= power; i++) {
tester.calculatePower(i);
System.out.println(tester.getPower());
}
Private implementation
public void calculatePower(int iPower) {
result = (int) Math.pow(target, iPower);
}
public int getPower() {
return result;
}
I need to call GetNewItem function million times;
Items XY = GetNewItem(X, Y);
Items XYZ = GetNewItem(XY, Z);
Items XZ = GetNewItem(X, Z);
Items YZ = GetNewItem(Y, Z);
This function aims to
1- find intersection between ArrayList of structure namely
ArrayList<Records> RecordLists
2- and it also calculates the probability for the new ArrayList , this is my code:
class Records {
public int RecordId;
public double Prob;
}
class Items {
public ArrayList<Integer> itemId;
public ArrayList<Records> RecordLists;
public double ItemProb = 0.0;
};
private ArrayList<Records> Intersection(ArrayList<Records> list1, ArrayList<Records> list2) {
ArrayList<Records> Result = new ArrayList<>();
int i = 0, j = 0;
while (i < list1.size() && j < list2.size()) {
if (list1.get(i).RecordId== (list2.get(j).RecordId)) {
Records RecordDetails= new Records();
RecordDetails.RecordId= list1.get(i).RecordId;
RecordDetails.Prob+= 1;
Result.add(RecordDetails);
i++;
j++;
} else if (list1.get(i).RecordId < list2.get(j).RecordId) {
i++;
} else if (list1.get(i).RecordId > list2.get(j).RecordId) {
j++;
}
}
return Result;
}
public Items GetNewItem(Items item1, Items item2) {
Items NewItem = new Items ();
ArrayList<Integer> newItemId = new ArrayList<>();
newItemId.addAll(item1.itemId);
newItemId.addAll(item2.itemId);
NewItem.itemId = newItemId;
NewItem.RecordLists= Intersection(item1.RecordLists,item2.RecordLists);
NewItem.ItemProb = getProb(NewItem.RecordLists);
return NewItem ;
}
private double getProb(ArrayList<Records> RProb) {
double IProb = 0.0;
for (int i = 0; i < RProb.size(); i++) {
IProb += RProb.get(i).Prob;
}
return IProb ;
}
For this code I got 'out of memory error'
I don't know how to save the memory and time, I tried this solution:
java.lang.OutOfMemoryError: Java heap space with NetBeans
but my computer did freeze. I don't know what else I have to do.
Please use java conventions, e.g. variables in camel case, non public variables in classes (use getters/constructor/setters)
I'm not sure why are you getting the intersection that way, with that i and j variables.
Please try:
public <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
If you want to calculate something else maybe do it in a separate method?
Use floats instead of doubles.
Could you please paste whole code? I would like to reproduce this.
Given the following example code, please help me answer the following questions with hints
public class Coin
{
private String myColor;
private int mySideOne;
private double mySideTwo;
public Coin(String Color, int SideOne, double SideTwo)
{
myColor= Color;
mySideOne = SideOne;
mySideTwo = SideTwo;
}
//accessors getColor(), getSideOne(), and getSideTwo()
}
public class Total
{
private int myNumCoins;
private Coin[] moneyList;
//constructor
public Total(int myCoins)
{
myNumCoins = numCoins;
moneyList = new Coins[numCoins]
String color;
int mySideOne;
double mySideTwo;
for (int i = 0; i<numCoins; i++)
{
}
}
**
Question:
**
//Returns total amount for Coins
public double totalMoney()
{
double total = 0.0;
/* code to calculate
return total;
}
}
Which represents correct / code to calculate amount */ in the totalMoney method?
A. for (Coin t: moneyList)
total+= moneyList.getSideTwo();
B. for (Coin t: moneyList)
total+=t.getSideTwo();
I think A is right because the "t" in B. doesn't exist in the code. How am I wrong?
Let's evaluate the code using A.:
public double totalPaid()
{
double total = 0.0;
for (Ticket t:tickList)
total+= tickList.getPrice();
return total;
}
tickList is an array of Tickets. An array is an object which only has a static final field called length. So, tickList cannot have getPrice. This means, option A doesn't compile.
Let's evaluate the code using B.:
public double totalPaid()
{
double total = 0.0;
for (Ticket t:tickList)
total+=t.getPrice();
return total;
}
Here you state:
I think A is right because the "t" in B. doesn't exist in the code. How am I wrong?
In fact, t is a variable declared and used in the enhanced for loop statement. t is from type Ticket and it will take the value of each Ticket object reference stored in tickList. The enhanced for loop can be translated to this form for arrays:
for (int i = 0; i < tickList.length; i++) {
Ticket t = tickList[i];
//use t in this scope
//in this case, it's used to accumulate the value of total
total += t.getPrice();
}
Which makes B as the solution for this problem.
The answer is B because you declare t in your loop when you say Ticket t. The loop iterates the ticketList and t will stand for each Ticket in the list.
What I need to do is find the inventory item with the lowest cost from an array list. If there are none, return "N/A". So I can't really figure out how to find the smallest value out of all the inventory item costs. This is what I have so far. My plan was to set cost equal to the first inventory item and cycle through each item checking if it's cost is less but I'm confused on how to do that or if that is even the correct way of doing it.
EDIT: We have not covered for loops yet so I cannot use them. I can only use while loops
public InventoryItem itemWithLowestCost() {
if (inventoryList.size() > 0) {
int i = 0;
while (i < inventoryList.size()) {
double cost = inventoryList.get(i).getCost();
if (cost < )
}
}
else {
return "N/A";
}
}
Here is my InventoryItem constructor. I'm not sure if this is needed to understand the above code but here it is anyway
public InventoryItem(String descriptionIn, double costIn, double percentDepreciatedIn) {
description = descriptionIn.trim();
cost = costIn;
percentDepreciated = percentDepreciatedIn;
}
You can do it by checking the length to be non-zero, then picking the cost of element zero as "tentative best", and comparing it to costs of other elements on the list:
if (inventoryList.size() > 0) {
int best = 0;
int i = 1;
while (i < inventoryList.size()) {
double cost = inventoryList.get(i).getCost();
if (cost < inventoryList.get(best).getCost()) {
best = i;
}
i++;
}
return inventoryList.get(best);
} else {
return "N/A";
}
You can do it with a O(n) loop
public InventoryItem itemWithLowestCost() {
int size = (inventoryList == null || inventoryList.isEmpty()) ?
0 : inventoryList.size();
InventoryItem min = (size > 0) ? inventoryList.get(0) : null;
for (int i = 1; i < size; i++) {
InventoryItem ii = inventoryList.get(i);
if (ii.getCost() < min.getCost()) min = ii;
}
return min;
}
Note: That you can't return a String N/A as an InventoryItem instance (so this returns null).
You could use a comparitor to sort the inventory by cost, lowest to highets.
public InventoryItem itemWithLowestCost(Collection<InventoryItem> inventory) {
if(inventory != null && !inventory.isEmpty()) {
Collections.sort(inventory, new Comparator<InventoryItem>() {
#Override
public int compare(InventoryItem i1, InventoryItem i2) {
return i1.getCost() - i2.getCost();
}
});
return inventory.get(0);
}
return null;
}
I am trying to extend ArrayList with a simple class that shows and updates a total every time a value is added. Why is it that iterating through this list in the manner that I have done below only allows it to iterate through everything but the very last element added to this ArrayList?
Why is it that the following shows my total to be 6 when it should be 13?
import java.util.*;
public class Test2 {
public static void main (String [] args){
IntStruct ints = new IntStruct();
ints.add(1);
ints.add(5);
ints.add(7);
}
}
class IntStruct extends ArrayList <Integer>{
private int total;
boolean add (int i){
setTotal();
return super.add(i);
}
void setTotal(){
total = 0;
for (int i : this){
System.out.println("Adding " + i + " to our total..");
total = total + i;
}
System.out.println("The total is now " + total);
}
}
You are calling setTotal() before you call super.add(i) to actually add the item, so the latest item isn't present when you compute the new total.
Try this:
boolean add (int i) {
if (super.add(i)) {
setTotal();
return true;
}
return false;
}
Not directly related to your question, but it would be more appropriate not to iterate over the list in order to calculate the total, e.g.
class IntStruct extends ArrayList <Integer>{
private int total = 0;
boolean add (int i){
return super.add(i);
total += i;
}
}