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.
Related
I have a java class in which I store an Enum.(shown at the bottom of this question) In this enum, I have a method named toCommaSeperatedString() who returns a comma separated String of the enums values. I am using a StringBuilder after reading some information on performance in this question here.
Is the way I am converting this enum's values into a commaSeperatedString the most efficient way of doing so, and if so, what would be the most efficient way to remove the extra comma at the last char of the String?
For example, my method returns 123, 456, however I would prefer 123, 456. If I wanted to return PROPERTY1, PROPERTY2 I could easily use Apache Commons library StringUtils.join(), however, I need to get one level lower by calling the getValue method when I am iterating through the String array.
public class TypeEnum {
public enum validTypes {
PROPERTY1("123"),
PROPERTY2("456");
private String value;
validTypes(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static boolean contains(String type) {
for (validTypes msgType : validTypes.values()) {
if (msgType.value.equals(type)) {
return true;
}
}
return false;
}
public static String toCommaSeperatedString() {
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for(validTypes msgType : validTypes.values()) {
commaSeperatedValidMsgTypes.append(msgType.getValue() + ", ");
}
return commaSeperatedValidMsgTypes.toString();
}
}
}
I wouldn't worry much about efficiency. It's simple enough to do this that it will be fast, provided you don't do it in a crazy way. If this is the most significant performance bottleneck in your code, I would be amazed.
I'd do it something like this:
return Arrays.stream(TypeEnum.values())
.map(t -> t.value)
.collect(Collectors.joining(','));
Cache it if you want; but that's probably not going to make a huge difference.
A common pattern for the trailing comma problem I see is something like
String[] values = {"A", "B", "C"};
boolean is_first = true;
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for(String value : values){
if(is_first){
is_first = false;
}
else{
commaSeperatedValidMsgTypes.append(',');
}
commaSeperatedValidMsgTypes.append(value);
}
System.out.println(commaSeperatedValidMsgTypes.toString());
which results in
A,B,C
Combining this with the answers about using a static block to initialize a static final field will probably give the best performance.
The most efficient code is code that doesn't run. This answer can't ever change, so run that code as you have it once when creating the enums. Take the hit once, return the calculated answer every other time somebody asks for it. The savings in doing that would be far greater in the long term over worrying about how specifically to construct the string, so use whatever is clearest to you (write code for humans to read).
For example:
public enum ValidTypes {
PROPERTY1("123"),
PROPERTY2("345");
private final static String asString = calculateString();
private final String value;
private static String calculateString() {
return // Do your work here.
}
ValidTypes(final String value) {
this.value = value;
}
public static String toCommaSeparatedString() {
return asString;
}
}
If you have to call this static method thousand and thousand of times on a short period, you may worry about performance and you should first check that this has a performance cost.
The JVM performs at runtime many optimizations.
So finally you could write more complex code without added value.
Anyway, the actual thing that you should do is storing the String returned by toCommaSeperatedString and returned the same instance.
Enum are constant values. So caching them is not a problem.
You could use a static initializer that values a static String field.
About the , character, just remove it after the loop.
public enum validTypes {
PROPERTY1("123"), PROPERTY2("456");
private static String valueSeparatedByComma;
static {
StringBuilder commaSeperatedValidMsgTypes = new StringBuilder();
for (validTypes msgType : validTypes.values()) {
commaSeperatedValidMsgTypes.append(msgType.getValue());
commaSeperatedValidMsgTypes.append(",");
}
commaSeperatedValidMsgTypes.deleteCharAt
(commaSeperatedValidMsgTypes.length()-1);
valueSeparatedByComma = commaSeperatedValidMsgTypes.toString();
}
public static String getvalueSeparatedByComma() {
return valueSeparatedByComma;
}
I usually add a static method on the enum class itself:
public enum Animal {
CAT, DOG, LION;
public static String possibleValues() {
return Arrays.stream(Animal.values())
.map(Enum::toString)
.collect(Collectors.joining(","));
}
}
So I can use it like String possibleValues = Animal.possibleValues();
EDIT: Added some information.
I got an array of Objects. Each object has a name and a value. I need to sort the objects in descending order of those values, and print the names. I saw this easy solution but can't seem to apply it to my problem: http://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/
The code compiles with no error but the array is not sorted at all. I know this because I know what the output should be i.e. the output should be something like var364, var200, var65 etc. and what i get is var1, var2, var3 etc.
I tried to strip the code of the irrelevant parts here:
Main class
print(data.preselection());
private void print (UnitRow preselectedUnitRow) {
out.printf("Variables after preselection: \n");
for (int i=0;i<PRESELECTION_LIMIT;i++) {
out.printf("%s, ",preselectedUnitRow.getUnitName(i));
}
}
Dataset (data)
private UnitRow data;
...
public UnitRow preselection() {
UnitRow standardDeviationUnits = new UnitRow(numberOfVariables);
for (int i=0;i<numberOfVariables;i++){
Unit unit = new Unit(1,variableNames[i],calculateStandardDeviation(i));
standardDeviationUnits.add(unit);
}
standardDeviationUnits.sort();
return standardDeviationUnits;
}
UnitRow
import java.util.Arrays;
public class UnitRow {
private Unit[] units;
private int count;
...
public void sort() {
Arrays.sort(units);
}
}
Unit
public class Unit implements Comparable<Unit>{
private NumberRow elements; //just a class with an array of doubles
private String name;
...
#Override
public int compareTo(Unit compareUnit) { //getValue returns a single type double number
int comparison = (int) (compareUnit.getValue(0) - getValue(0));
return comparison;
}
}
I am assuming my implementation of Comparable is wrong. Can you spot the problem?
I say this because I tested as following:
System.out.println(standardDeviationUnits.getValue(0,0));
standardDeviationUnits.sort();
System.out.println(standardDeviationUnits.getValue(0,0));
And the exact same value is returned.
It looks like reverse order
public int compareTo(Unit compareUnit) {
if (getValue(0) < compareUnit.getValue(0)) return 1;
else if (getValue(0) > compareUnit.getValue(0)) return -1;
return 0;
}
Try this.
Also note that in your compareTo, you unnecessarily wrote return 2; and wrote 3 if instead of 1 if-else.
If you are trying to sort as per names:
return compareUnit.name.compareTo(name);
else I have no idea what attribute your getValue(0) returns to you but still if you are trying to sort as per getValue(0):
return compareUnit.getValue(0)-getValue(0);
I'm trying to create a counter that will rollover whenever it reaches a preset ceiling and resets back to its floor value upon reaching said ceiling. I have implemented the class and it works just fine. However, on my way to my solution, I wanted to experiment with Java Generics. I want to try and extend my counter so that it doesn't only use integers, but instead can use any type of number. I know that counters typically call for just the use of integers anyway, but I wanted to see if it could be done.
I figured that the code would be similar to below. However, java.lang.Number doesn't have a "generic" way of getting/setting its value. Do I need to create my own number class to enable this? Also, I know that if I do get this working, I need to alter my equals checks so that they have an error threshold for floating point values, this is more or less a modified version of my int counter with what I figured would work for generics.
Edit:
It's been suggested that I take a mapping approach where I store an integer counter and keep a increment value so that when I want to spit out a number, I just multiply my current count by the increment value. However, I don't believe this will fill my exact needs because I don't want to necessarily increment by the same amount every time. The main focus of this counter is more of a way to have a fixed range number that, when added to or subtracted from, knows how to handle wrapping back around.
I guess the best way to describe it (although probably improperly) would be like an Integer that automatically handles over/underflow.
package com.math;
public class GenericRolloverCounter<T extends Number> {
private T value;
private T lowValue;
private T highValue;
public GenericRolloverCounter(T l_startValue, T l_highValue) {
this.lowValue = l_startValue;
this.highValue = l_highValue;
this.value = l_startValue;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public void increment(T valToIncrementBy) {
this.value += valToIncrementBy;
if (this.value > this.highValue) {
this.value = (this.lowValue + (this.value - (this.highValue + 1)));
}
}
public void increment() {
this.increment(1);
}
public void decrement(T valToDecrementBy) {
this.value -= valToDecrementBy;
if (this.value < this.lowValue) {
this.value = ((this.value + this.highValue + 1) - this.lowValue);
}
}
public void decrement() {
this.decrement(1);
}
#Override
public String toString() {
return Integer.toString(this.value);
}
}
You might want to also specify an amount by which to count. Default value would be 1.
You can get around some of this by using the Number method .doubleValue() and doing double arithmetic.
Here is one of the methods converted to use this idea.
public void decrement(double valToDecrementBy) {
double work = this.value.doubleValue();
work -= valToDecrementBy;
// should use some value related to incrementing amount
if ((this.value.doubleValue() - this.lowValue.doubleValue()) < 0.1D) {
work = ((this.value.doubleValue() + this.highValue.doubleValue() + 1) - this.lowValue.doubleValue());
}
// ... no way to put it back
}
But, there is still no way to put the value back that's clean and easy. Since 'Number' only has a few commonly used non-abstract subclasses, you could do some ugly instanceof stuff to store the value back. It would look something like this:
if (theValue instanceof Double) { // depends on it having a non-null value prior
theValue = (T)(new Double(work));
}
Or you could convert the starting values to double when you start and just work with doubles.
private double value;
private double lowValue;
private double highValue;
public GenericRolloverCounter(T l_startValue, T l_highValue) {
this.lowValue = l_startValue.doubleValue();
this.highValue = l_highValue.doubleValue();
this.value = l_startValue.doubleValue();
}
That does introduce the issues of incrementing floating point values and the rounding/evaluation problem there.
Oh ... and your toString() should be:
return value.toString();
To use the native toString() method on the T class.
#Crusher's comments suggest another way to do it. Map everything to 'int' and keep a multiplier. Here's some bits of code to show what I mean. (Thanks Crusher)
private int value;
private int lowValue;
private int highValue;
private double incr;
public GenericRolloverCounter(T l_startValue, T l_highValue, T incrementAmount) {
double incr = incrementAmount.doubleValue();
this.lowValue = Math.round(l_startValue.doubleValue() / incr);
this.highValue = Math.round(l_highValue.doubleValue() / incr);
this.value = Math.round(l_startValue.doubleValue() / incr);
}
public void increment(int valToIncrementBy) {
this.value += valToIncrementBy;
if (this.value > this.highValue) {
this.value = (this.lowValue + (this.value - (this.highValue + 1)));
}
}
#Override
public String toString() {
return String.valueOf(incr * this.value);
}
I am going through previous exam questions and my question is what is the correct way or ways to determine a String length and return it.
If the String is less than 5 characters in length then I can return it the following way:
public static String first5(String s){
if(s.length() < 5)
return s;
}
If the String is greater than 5 characters though, it can be returned in the following way:
public static String first5(String s){
return s.substring(0, 4);
}
What I must note is that when I answered this type of question before in an in class test, my lecturer stressed that I should not really use 'magic numbers'?
I am not sure what he actually meant by that though.
Is there a better way to return this type of method at all?
I am still learning Java so please forgive any errors in my syntax.
Many thanks.
This should be your method first5:
public static String first5(String s){
return s.length() < 5? s : s.substring(0, 5);
}
There are no magic numbers here, but maybe the teacher meant the number 5 was a magic number and wanted you to generalize the function:
public static String firstN(String s, int n){
return s.length() < n? s : s.substring(0, n);
}
Note that there's no great shame in using an if statement:
String r = null;
if (s.length() < 5) {
r = s;
}
else {
r = s.substring(0,5);
}
return r;
The logic is clearer than if you use ?:. The advantage of the latter is that it occupies less screen real-estate, so you can get more of a large function onto a screen -- valuable if you have a large function, but counter-productive if not.
Essentially if the requirements ever change, you can easily change the value in one location; thus, it will be changed everywhere it's referenced. You won't have to worry about any fragments of the old requirements floating around in the code. This is generally a good rule to follow with a large chunk of code.
public class solution {
static final int VAR1 = 0;
static final int VAR2 = 4;
static final int VAR3 = 5;
public static String first5(String s){
if(s.length() < VAR3) {
return s;
} else {
return s.substring(VAR1, VAR2);
}
}
}
Of course the variable names will have to be named something meaningful to the class/application itself.
Is the number 5 is in your question? If not get the number as input argument with the string input.
How can I improve this?
The relationship is one to one and continuous on [-1,5] so i was thinking of using enum, but I'm not sure how to compare a string value to an enum value.
If there is any better way to do this, please suggest.
Thanks!
private int evaluateWord(String sval) {
if (sval.equals("program"))
return 1;
else if (sval.equals("begin"))
return 2;
else if (sval.equals("end"))
return 3;
else if (sval.equals("int"))
return 4;
else if (sval.equals("if"))
return 5;
else
System.exit(0);
Have you considered stuffing the mapping into a HashMap once, and then just querying the map?
For example, something like this:
private static final Map<String,Integer> m_map = new HashMap<String,Integer>();
static {
m_map.put( "program", 1 );
m_map.put( "begin", 2 );
m_map.put( "end", 3 );
m_map.put( "int", 4 );
m_map.put( "if", 5 );
}
private int evaluateWord(String sval) {
Integer value = m_map.get( sval );
if ( null != value ) {
return value;
}
else {
System.exit(0);
}
}
By the way, it looks as if you're writing a parser. It can be reasonable to write a parser by hand. Another option to consider, unless you have a good reason to write it by hand, is a parser generator like ANTLR.
Using an enumeration:
enum Word {
PROGRAM(1,"program"),
BEGIN(2,"begin"),
END(3,"end"),
INT(4,"int"),
IF(5,"if");
private final int value;
private final String representation;
Word(int value, String representation)
{
this.value = value;
this.representation = representation;
}
public int value()
{ return value; }
private static Map<String, Word> fromRep =
new HashMap<String, EnumExample2.Word>();
public static Word fromRepresentation(String rep) {
if (!validRep(rep)) {
throw new IllegalArgumentException("No rep: "+rep);
}
return fromRep.get(rep);
}
public static boolean validRep(String rep)
{ return fromRep.get(rep) != null; }
static {
for (Word word : Word.values()) {
fromRep.put(word.representation, word);
}
}
}
Then your logic is:
private int evaluateWord(String sval) {
if (!Word.validRep(sval)) {
System.exit(0);
}
return Word.fromRepresentation(sval).value();
}
A hashmap could work:
private static HashMap<String, Integer> lookup = new HashMap<String, Integer>();
static {
lookup.put("program", 1);
lookup.put("being", 2);
lookup.put("end", 3);
lookup.put("int", 4);
lookup.put("if", 5);
}
private int evaluateWord(String sval) {
if ( lookup.containsKey(sval) ) {
return lookup.get(sval);
}
System.exit(0);
}
This is what a map is for;
Create a HashMap, add key and values to the map like
wordMap.put("program", Integer.valueOf(1));
....
then, to get the value do
Integer val = wordMap.get(sval);
Honestly, I wouldn't worry about keeping something like this ultra efficient, but there is a change you could make. If the word you pass is the last word you check for then your program ends up performing all of the checks in your function. This shouldn't be a problem in this case, but generally you don't want to flood your program with if statements, especially if you have a lot of cases.
Use a hashtable and just insert pairs. This way, all of your evaluateWord calls will return in amortized constant time. :)
Good luck!
Why do you need a (very subjective) "cleaner" way?
You could get more efficiency from using a hash lookup but you'd want to be certain it's called quite a bit to make the extra coding effort worthwhile. If it's something that happens infrequently (and, by that, I mean something like less than once a second), it's not worth doing (YAGNI).
One thing you might want to do for better looking code (if that's important) is to ditch the else bits, they're totally unnecessary:
private int evaluateWord(String sval) {
if (sval.equals("program")) return 1;
if (sval.equals("begin")) return 2;
if (sval.equals("end")) return 3;
if (sval.equals("int")) return 4;
if (sval.equals("if")) return 5;
System.exit(0);
}
You could just use an array or hashmap to map the enum values to the string values.
Inspired by your enum comment, I present the following. It's a bit hackish, but:
enum Word
{
PROGRAM (1), BEGIN (2), END (3), INT (4), IF (5);
public int value;
public Word (int value)
{
this.value = value;
}
};
int evaluateWord (String word)
{
return Word.valueOf(word.toUpperCase( )).value;
}
I love Java enums because you can do things like this. This is especially useful if you later want to (for example) add a unique behaviour for each word, or to maintain a long list of words. Note though that it is case insensitive.
Or, alternately:
enum Word
{
PROGRAM, BEGIN, END, INT, IF;
};
int evaluateWord (String word)
{
return Word.valueOf(word.toUpperCase( )).ordinal( ) + 1;
}