my professor gave me an exercise to find how many time the characters of string called "filter" are to be found in a second string called "query".
before I begin I am java noob and English isnt my native language.
example:
String filter="kjasd";
String query="kjg4t";
Output:2
getting how many times a char has been found in another string isnt my problem but the problem that the professor gave us some rules to stick with:
class filter. The class must be the following public
Provide interfaces:
public Filter (String letters) (→ Constructor of class)
The string representing the filter should be stored in the letters string
public boolean contains (char character)
Returns true if the passed character is contained in the query string, otherwise false
-public String toString ()
Returns an appropriate string representation of the class (just to be clear I have no clue about what does he means with this one!)
To actually determine the occurrences of the filter in the query, another class QueryResolver is to be created.
The class should be able to be used as follows:
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
the filter and the query are given by the user.
(i couldnt understand this one! )The methods "where" and "matches" configure the "QueryResolver" to include a subsequent call of "count" the calculation based on the previously passed variables
"query" and "filter" performs.
The count method should use the filter's previously-created method.
The modifier static is not allowed to use!
I dunno if he means that we cant use static {} or we cant use public (static) boolean contains (char character){}
we are not allowed to use void
so the problems that encountered me
- I can not pass a char to the method contains as long as it is not static.
error "Non-static variable can not be referenced from a static context"
i did not understand what i should do with the method toStirng!
what I've done so far:
Approach Nr 1:
so I just wrote everything in the main method to check whether the principle of my code works or not and then I wanted to create that whole with constructor and other methods but unfortunately I did not succeed.
Approach Nr 2:
then I tried to write the code in small mthoden as in the exercise but I did not succeed !.
in both aprroaches i violated the exercise rules but i cant seem to be able to do it alone thats why i posted the question here.
FIRST APPROACH:
public class filter{
public filter(String letters) {
//constructor of the class
String filter;
int count;
}
public boolean contains (char character){
/*Subprogram without static!
*the problem that I can't pass any char to this method if it wasn't static
*and I will get the following error"Non-static variable cannot be referenced from a static context"
*I understand why I'm getting the error but I don't know how to get around it X( */
return true ;
}
public String toString (){
/*he told us to include it in the program but honestly, I don't know what shall I write in it -_-
*I make it to null because you have to return something and I don't know what to do yet
*so, for now, I let it null. */
return null;
}
public static void main(String[] args) {
Scanner in =new Scanner (System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
int count=0;
// I initialized it temporarily because I wanted to print it!
//later I need to use it with the boolean contains as a public method
boolean contains=false;
//to convert each the query and the filter strings to chars
char [] tempArray=query.toCharArray();
char [] tempArray1=filter.toCharArray();
//to iterate for each char in the query string!
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
//to iterate for each char in the filter string!
for (int j = 0; j < tempArray1.length; j++) {
// if the value in the filter string matches the value in the temp array then increment the counter by one!
if(tempArray1[j] == cc){
count++;
contains=true;
}
}
}
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
System.out.println("the boolean value : "+ contains);
in.close();
}
}
SECOND APPROACH
- But here too I violated the rules of the task quite brutally :(
- First, I used void and did not use the tostring method.
- Second, I did not use a constructor.
- I did not add comments because that's just the same principal as my first attempt.
public class filter2 {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
System.out.println("enter the filter string:");
String filterStr=in.next();
System.out.println("enter the query string:");
String querystr =in.next();
Filter(filterStr, querystr);
in.close();
}
public static void Filter(String filterstr , String querystr){
char [] tempArray1 = filterstr.toCharArray();
contains(tempArray1, querystr);
}
public static void contains(char[]tempArray1, String querystr){
boolean isThere= false ;
int counter=0;
char [] tempArray = querystr.toCharArray();
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
for (int j = 0; j < tempArray1.length; j++) {
if(tempArray1[j] == cc){
counter++;
isThere=true;
}
}
}
System.out.println("the letters of the filter string has been found in the query string exactly "+counter+" times!\nthus the boolean value is "+isThere);
}
/*
* sadly enough i still have no clue what is meant with this one nor whatshall i do
* public String toString (){
* return null;
* }
*
*/
}
Few hints and advice would be very useful to me but please demonstrate your suggestions in code because sometimes it can be difficult for me to understand what you mean by the given advice. ;)
Thank you in advance.
(sorry for the gramatical and the type mistakes; english is not my native language)
As already mentioned, it is important to learn to solve those problems yourself. The homework is not for punishment, but to teach you how to learn new stuff on your own, which is an important trait of a computer scientist.
Nonetheless, because it seems like you really made some effort to solve it yourself already, here is my solution, followed by some explanation.
General concepts
The first thing that I feel like you didn't understand is the concept of classes and objects. A class is like a 'blueprint' of an object, and the object is once you instanciated it.
Compared with something like a car, the class would be the description how to build a car, and the object would be a car.
You describe what a class is with public class Car { ... }, and instanciate an object of it with Car myCar = new Car();.
A class can have methods(=functions) and member variables(=data).
I just repeat those concepts because the code that you wrote looks like you didn't fully understand that concept yet. Please ask some other student who understood it to help you with that.
The Filter class
public class Filter{
String letters;
public Filter(String letters) {
this.letters = letters;
}
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
public String toString (){
return "Filter(" + letters + ")";
}
}
Ok, let's brake that down.
public class Filter{
...
}
I guess you already got that part. This is where you describe your class structure.
String letters;
This is a class member variable. It is unique for every object that you create of that class. Again, for details, ask other students that understood it.
public Filter(String letters) {
this.letters = letters;
}
This is the constructor. When you create your object, this is the function that gets called.
In this case, all it does is to take an argument letters and stores it in the class-variable letters. Because they have the same name, you need to explicitely tell java that the left one is the class variable. You do this by adding this..
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
This takes a character and looks whether it is contained in this.letters or not.
Because there is no name collision here, you can ommit the this..
If I understood right, the missing static here was one of your problems. If you have static, the function is class-bound and not object-bound, meaning you can call it without having an object. Again, it is important that you understand the difference, and if you don't, ask someone. (To be precise, ask the difference between class, object, static and non-static) It would take too long to explain that in detail here.
But in a nutshell, if the function is not static, it needs to be called on an object to work. Look further down in the other class for details how that looks like.
public String toString (){
return "Filter(" + letters + ")";
}
This function is also non-static. It is used whenever the object needs to be converted to a String, like in a System.out.println() call. Again, it is important here that you understand the difference between class and object.
The QueryResolver class
public class QueryResolver {
Filter filter;
String query;
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
}
Again, let's break that down.
public class QueryResolver {
...
}
Our class body.
Note that we don't have a constructor here. It is advisable to have one, but in this case it would be an empty function with no arguments that does nothing, so we can just leave it and the compiler will auto-generate it.
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
This is an interesting function. It returns a this pointer. Therefore you can use the result of the function to do another call, allowing you to 'chain' multiple function calls together, like resolver.where(query).matches(filter).count().
To understand how that works requires you to understand both the class-object difference and what exactly the this pointer does.
The short version is that the this pointer is the pointer to the object that our function currently lives in.
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
This is almost the same as the where function.
The interesting part is the new Filter(...). This creates the previously discussed Filter-object from the class description and puts it in the QueryResolver object's this.filter variable.
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
Iterates through the object's query variable and checks for every letter if it is contained in filter. It keeps count of how many times this happens and returns the count.
This function requires that filter and query are set. Therefore it is important that before someone calls count(), they previously call where(..) and matches(..).
In our case, all of that happens in one line, resolver.where(query).matches(filter).count().
The main function
I wrote two different main functions. You want to test your code as much as possible during development, therefore the first one I wrote was a fixed one, where you don't have to enter something manually, just click run and it works:
public static void main(String[] args) {
String filter="kjasd";
String query="kjg4t";
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println(count);
}
Once you understand the class-object difference, this should be straight forward.
But to repeat:
QueryResolver resolver = new QueryResolver();
This creates your QueryResolver object and stores it in the variable resolver.
int count = resolver.where(query).matches(filter).count();
Then, this line uses the resolver object to first call where, matches, and finally count. Again, this chaining only works because we return this in the where and matches functions.
Now finally the interactive version that you created:
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
in.close();
}
my class has a method as follow :
private volatile String currentSeqSecondBucket = "";
private volatile int currentUriSeq = 0;
public String calculateRepositoryURI(Date now, String userSpecifiedFolder)
{
String folder = userSpecifiedFolder;
if (StringUtils.isBlank(folder))
folder = RSIConstant.CONTENT_ROOT_FOLDER;
StringBuilder buf = new StringBuilder(folder);
if (!folder.endsWith("/"))
buf.append("/");
String nowStr = YYYYMMDDHHMMSS_FORMAT.format(now);
buf.append(String.valueOf((int)(Math.random() * 1000)));
buf.append("/");
buf.append(nowStr);
buf.append("_");
synchronized (this)// here the this means my class
{
if (currentSeqSecondBucket.equals(nowStr))
{
currentUriSeq++;
}
else
{
currentUriSeq = 1;
currentSeqSecondBucket = nowStr;
}
buf.append(String.valueOf(currentUriSeq));
}
buf.append(".xml");
return buf.toString();
}
Will this code return a unique string for every call?
Will this code return a unique string for every call?
No. It won't. But the reason is nothing to do with thread safety.
The reason is that occasionally you may get the same random number generated twice in the same second. Now if the same random number was generated twice in a row, then your test currentSeqSecondBucket.equals(nextStr) would catch this and you would increment currentUriSeq and avoid the collision. However, a more likely scenario is that the random number repeats after more than one call in the same second. That will defeat your test.
My advice would be to not try to re-invent the wheel:
If you want non-guessable unique names, use the UUID class to give you uniqueness.
If you don't care about guessability, just use a simple sequence number; e.g. implemented using AtomicInteger or AtomicLong.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm looking for some tip on how to do a percentage thing for my game I want all flowers in a range of 1-98 and white/black flowers 99-100 to make it more rarerity thanks for the help :)
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1 ),
RED_FLOWERS("red", ":red:", "470419583250202644", 1),
RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1),
PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1),
ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1),
BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1),
BLACK_FLOWERS("black", ":black:", "470419706751352842", 1);
private final String displayName;
private final String emoticon;
private int value;
private final String id;
FlowerSuit(String displayName, String emoticon, String id, int value ) {
this.displayName = displayName;
this.emoticon = emoticon;
this.value = value;
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public String getEmoticon() {
return emoticon;
}
public String getId() {
return id;
}
public int getValue() {
// TODO Auto-generated method stub
return value;
}
}
This is how I'd do it, but it can probably be improved, for starters by using Java 8 streams etc.
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1,3),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1,2),
RED_FLOWERS("red", ":red:", "470419583250202644", 1,2),
RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1,2),
PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1,2),
ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1,2),
BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1,2),
BLACK_FLOWERS("black", ":black:", "470419706751352842", 1,1);
private static Random random = new Random();
private final String displayName;
private final String emoticon;
private int value;
private final String id;
private final int freq;
private FlowerSuit(String displayName, String emoticon, String id, int value, int freq ) {
this.displayName = displayName;
this.emoticon = emoticon;
this.value = value;
this.id = id;
this.freq = freq;
}
public String getDisplayName() {return displayName;}
public String getEmoticon() {return emoticon;}
public String getId() {return id;}
public int getValue() {return value;}
/**
* Choose a flower
* white has a 3 in 16 (about a 5:1) chance of being picked
* Black has a 1 in 16 chance, everything else 2/16
* #return
*/
public static FlowerSuit pick() {
//first sum all the chances (currently it's 16)
int sum = 0;
for (FlowerSuit f:FlowerSuit.values()) sum+= f.freq;
//now choose a random number
int r = FlowerSuit.random.nextInt(sum) + 1;
//now find out which flower to pick
sum = 0;
for (FlowerSuit f:FlowerSuit.values()) {
sum += f.freq;
if (r<=sum) return f;
}
//code will never get here
return FlowerSuit.WHITE_FLOWERS;
}
public static void main(final String[] args) throws Exception {
//Test it
Map<FlowerSuit,Integer>count = new HashMap<FlowerSuit,Integer>();
for (int a=0;a<1000000;a++) {
FlowerSuit f = FlowerSuit.pick();
Integer i = (count.get(f)!=null)?count.get(f):new Integer(0);
i = new Integer(i+1);
count.put(f,i);
}
int sum = 0;
for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) sum+=e.getValue();
float f = Float.valueOf(sum);
for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) {
System.out.println(e.getKey() + " was chosen " + ((e.getValue() / f) * 100f) + "% of the time");
}
}
}
gives
BLUE_FLOWERS was chosen 12.4986% of the time
PASTEL_FLOWERS was chosen 12.4707% of the time
WHITE_FLOWERS was chosen 18.7365% of the time
BLACK_FLOWERS was chosen 6.2632003% of the time
ORANGE_FLOWERS was chosen 12.4986% of the time
RED_FLOWERS was chosen 12.5241995% of the time
YELLOW_FLOWERS was chosen 12.501401% of the time
RAINBOW_FLOWERS was chosen 12.5068% of the time
You can use a TreeMap to map all of the integers from 0 to 99 to a particular FlowerSuit. Take advantage of the floorEntry method to choose a FlowerSuit for each number. It might look something like this.
public class FlowerChooser {
private static final NavigableMap<Integer, FlowerSuit> FLOWER_SUITS;
private static final Random RANDOMS = new Random();
public FlowerChooser() {
FLOWER_SUITS = new TreeMap<>();
FLOWER_SUITS.put(0, FlowerSuit.RED_FLOWERS);
FLOWER_SUITS.put(14, FlowerSuit.ORANGE_FLOWERS);
FLOWER_SUITS.put(28, FlowerSuit.YELLOW_FLOWERS);
FLOWER_SUITS.put(42, FlowerSuit.GREEN_FLOWERS);
FLOWER_SUITS.put(56, FlowerSuit.BLUE_FLOWERS);
FLOWER_SUITS.put(70, FlowerSuit.INDIGO_FLOWERS);
FLOWER_SUITS.put(84, FlowerSuit.VIOLET_FLOWERS);
FLOWER_SUITS.put(98, FlowerSuit.WHITE_FLOWERS);
FLOWER_SUITS.put(99, FlowerSuit.BLACK_FLOWERS);
}
public FlowerSuit randomFlowerSuit() {
int index = RANDOMS.nextInt(100);
return FLOWER_SUITS.floorEntry(index).getValue();
}
}
Create just one object of this class, then whenever you want a FlowerSuit, call the randomFlowerSuit method.
The randomFlowerSuit method picks a random number from 0 to 99, then finds an appropriate entry in the map. The floorEntry method chooses an entry whose key is less than or equal to the chosen number. This means that numbers from 0 to 13 get mapped to red, 14 to 27 get mapped to orange, and so on. The only number that gets mapped to white is 98, and the only number that gets mapped to black is 99.
No matter what solution you implement, you want to include a frequency measure in your enum. As an example, you can do something like this:
public enum FlowerSuit {
WHITE_FLOWERS("white", ":white:", "470419377456414720", 1, 1),
YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1, 20),
// More declarations here
// Add this variable
private final int frequency;
// Do just as you did before in the constructor, but with the frequency
FlowerSuit(String displayName, String emoticon, String id, int value, int frequency){
this.frequency = frequency;
// More assignments here
}
public int getFrequency(){
return frequency;
}
// More getters here
}
This addition is critical, and no matter what method you use to weight flower selection, you will want this addition to your FlowerSuit enum.
Now, we can explore a few different ways to perform this selection.
Note 1: I use ThreadLocalRandom for random numbers in a range, which is from java.util.concurrent.ThreadLocalRandom.
Note 2: For each of these, make a single instance of FlowerPicker, and use the pickFlower() method to pick the next flower. This avoid running costly setup code over and over.
Method 1: Bag of Flowers
This method is probably the easiest to implement. It entails creating a list of enums where each is represented frequency times, and then selecting a random entry from this list. It is similar to throwing a bunch of flowers in a bag, shaking it, and then reaching your hand in and grabbing the first flower you touch. Here's the implementation:
public class FlowerPicker(){
private ArrayList<FlowerSuit> bag;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
// You can use an array here or an array list with a defined length if you know the total of the frequencies
bag = new ArrayList<FlowerSuit>();
// Add each flower from options frequency times
for (FlowerSuit flower : options)
for (int i=0; i<flower.getFrequency(); i++)
bag.add(flower);
}
public FlowerBag pickFlower(){
// Now, select a random flower from this list
int randomIndex = ThreadLocalRandom.current().nextInt(0, bag.size());
return bag.get(randomIndex);
}
}
This method has the advantage of being simple enough to understand very easily. However, it can be inefficient if your frequencies are extremely specific (like if you want a rainbow flower to be returned 499,999,999 times out of 1,000,000,000). Let's move on to the next method.
Note 1: You could make this better by reducing the fractions representing the frequency of being chosen, but I'll leave this to you.
Note 2: You could also make this slightly better by storing identification numbers, not FlowerSuit objects in the bag list.
Method 2: Navigable Map
This method is a little bit more difficult. It uses a [NavigableMap][1], which is an implementation of [TreeMap][2]. This method is fairly similar to the Bag of Flowers method, but it is a little bit more efficient. Put simply, it uses the TreeMap to give each FlowerSuit a range of numbers that can be selected to return that FlowerSuit. Here's a full example:
public class FlowerPicker(){
private NavigableMap<Double, FlowerSuit> map;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
map = new TreeMap<Double, FlowerSuit>();
int runningTotal = 0;
// Add each flower with the proper range
for (FlowerSuit flower : options){
runningTotal += flower.getFrequency();
map.put(runningTotal, flower);
}
}
public FlowerBag pickFlower(){
// Now, select a random number and get the flower with this number in its range
int randomRange = ThreadLocalRandom.current().nextInt(0, bag.size());
return map.higherEntry(randomRange).getValue();
}
}
This is a solid method, and it scales well for very specific frequencies. If you have a bunch of different types of flowers, it will be slightly worse, but this method is still a good option at large scales. There's one more option though.
Method 3: Enumerated Distribution
This method is really nice because you barely have to do anything. However, it uses [EnumeratedDistribution][3] from Apache Commons. Enumerated Distribution requires a list of pairs of objects and weights. Anyway, lets jump into it:
public class FlowerPicker(){
private EnumeratedDistribution distribution;
public FlowerPicker(){
// Get all possible FlowerSuits
FlowerSuit[] options = FlowerSuit.values();
List<Pair<FlowerSuit, Double>> weights = new List<Pair<FlowerSuit, Double>>();
// Add each flower and weight to the list
for (FlowerSuit flower : options){
weights.add(new Pair(flower, flower.getFrequency()));
// Construct the actual distribution
distribution = new EnumeratedDistribution(weights);
}
public FlowerBag pickFlower(){
// Now, sample the distribution
return distribution.sample();
}
}
This is my favorite method, simply because so much of it is done for you. Many problems like this have been solved, so why not use solutions that always exist? However, there is some value to writing the solution yourself.
In conclusion, each of these methods are perfectly fine to use at your scale, but I would recommend the second or third method.
I'm writing a program that acts as a 'pocket' where the user is able to enter a kind of coin, such as, a quarter and the amount of quarters it has. I was assigned to do 3 different class, the Coin Class in which the coins and their values can be instatiated from, a Pocket Class, where I have to write a method that can add the coins of the user (basically the method would act like ArrayList .add() ) and the PocketClass tester. I have already written most of the code, but I am stuck as to how I could write the following method:
public void addCoin(String s, int i)
{
// s is type of coin, you are using s to instantiate a Coin and get value
// i is number of coins, you are using i to keep adding value to the totalValue
}
My question is how should I approach this? I am not quite clear on how to create method. Would I use a for-loop in order to keep track of the number of coins? I understand that the addCoin method works a lot like .add() from ArrayList.
Here is the code from my other classes:
public class Coin
{
private final String DOLLAR = "DOLLAR";
private final String QUARTER = "QUARTER";
private final String DIME = "DIME";
private final String NICKEL = "NICKEL";
private final String PENNY = "PENNY";
private int value;
private String coinName;
public Coin(String s,int count)//name of the coin and also the number of the coins you have
{
//Use if or switch statement to identify incoming string and provide value
double value=0;
if(DOLLAR.equalsIgnoreCase(s))
{
value=100.0;
}
else if(QUARTER.equalsIgnoreCase(s))
{
value=25.0;
}
else if(DIME.equalsIgnoreCase(s))
{
value=10.0;
}
else if(NICKEL.equalsIgnoreCase(s))
{
value=5.0;
}
else if(PENNY.equalsIgnoreCase(s))
{
value=1.0;
}
}
public int getValue()
{
return value;
}
}
and how the Pocket class is structured:
public class Pocket
{
private int currentValue;
private int totalValue;
private Coin quarter;
private Coin dime;
private Coin nickle;
private Coin penny;
public Pocket()
{ //Set initial value to zero
totalValue = 0;
currentValue = 0;
}
public void addCoin(String s, int i)
{
// s is type of coin, you are using s to instantiate a Coin and get value
// i is number of coins, you are using i to keep adding value to the totalValue
}
public int getValue()
{
return totalValue;
}
public void printTotal()
{
//print out two different output
}
}
I'm assuming you're adding the addCoin method in the Pocket class.
If you intend to keep track of the number of coins of each type within a Pocket, the simplest way to do so would be to declare a Hashmap that is keyed by the coin type (say, a "quarter" or a "dollar") and valued by the number of coins of that type. An invocation of the addCoin(type, count) method, say addCoin("dollar", 5) can then check if the hashmap already contains a key named "dollar" and if present, increment it's value by count.
I would suggest storing coins in a list so that you can add unlimited number of them.
Example:
class Coin{
//Same as your code....
public Coin(String coinType){
//..Same as your code, but removed number of coins
}
}
public class Pocket
{
private int currentValue;
private int totalValue;
//Create a list of coins to store unlimited number of coins
// A pocket can half 5 dimes
List coins;
public Pocket(){
//Set initial value to zero
totalValue = 0;
currentValue = 0;
coins = new ArrayList<Coin>();
}
/**
* This method will take only one coin at a time
**/
public void addCoin(String s){
Coin c = new Coin(s);
coins.add(c);
totalValue+=c.getValue();
}
/**
* This method will take any number of coins of same type
**/
public void addCoin(String s, int c){
//Add each one to array
for(int i=0;i<c;i++)[
addCoin(s);
}
}
}
I am not in favor of keeping multiple coin values in one Coin object because of the fact it is not a true representation of an object. What does that mean is tomorrow if you want to store other Coin attributes like "Printed Year", "President Picture on the coin" etc, you will have hard time. In my opinion it is better to represent one real world object (one coin here) using one object instance in the program,
Are there any existing utilities like Apache Commons StringUtils that make it easy to increment an integer, but output it as a zero padded string?
I can certainly write my own utilizing something like String.format("%05d", counter), but I'm wondering if there is a library that has this already available.
I'm envisioning something I can use like this:
// Create int counter with value of 0 padded to 4 digits
PaddedInt counter = new PaddedInt(0,4);
counter.incr();
// Print "0001"
System.out.println(counter);
// Print "0002"
System.out.println(counter.incr());
String text = "The counter is now "+counter.decr();
// Print "The counter is now 0001"
System.out.println(text);
I doubt you'll find anything to do this, because padding and incrementing are two basic operations that are unrelated, and trivial to implement. You could have implemented such a class three times in the time you took to write your question. It all boils down to wrapping an int into an object and implementing toString using String.format.
In case anyone is interested, I threw together this a few minutes after posting my question:
import org.apache.commons.lang.StringUtils;
public class Counter {
private int value;
private int padding;
public Counter() {
this(0, 4);
}
public Counter(int value) {
this(value, 4);
}
public Counter(int value, int padding) {
this.value = value;
this.padding = padding;
}
public Counter incr() {
this.value++;
return this;
}
public Counter decr() {
this.value--;
return this;
}
#Override
public String toString() {
return StringUtils.leftPad(Integer.toString(this.value),
this.padding, "0");
// OR without StringUtils:
// return String.format("%0"+this.padding+"d", this.value);
}
}
The only problem with this is that I must call toString() to get a string out of it, or append it to a string like ""+counter:
#Test
public void testCounter() {
Counter counter = new Counter();
assertThat("0000", is(counter.toString()));
counter.incr();
assertThat("0001",is(""+counter));
assertThat("0002",is(counter.incr().toString()));
assertThat("0001",is(""+counter.decr()));
assertThat("001",is(not(counter.toString())));
}
To be honest, I think you are mixing different concerns. An integer is an integer with all the operations and if you want to output it padded with zeros that is different thing.
You might want to have a look at StringUtils.leftPad as an alternative of String.format.