How to get the base pointer of Unicode character? - java

Currently I have "codePointAt" which returns the code point of the character from the string.
Is there any API or other way to get the base pointer of the current character?
public class Testclass {
public static void main(String[] args) {
String unicodeString = "कागज़";
int currentPoint = unicodeString.codePointAt(0);
// Now currentPoint = 0x0915
// I need currentPoint = 0x0900
}
}
Note# I cannot create the base pointer by addition/subtraction because different language's base point start from different One's/Ten's place values. For e.g.
Armenian - 0530-058F - Base pointer 0x0530(ten's place value)
Devanagari - 0900-097F - Base pointer 0x0900(hundred's place value)
Currently I'm using if-else blocks to get the base pointer which not dynamic and also lengthy approach. :-(
int basePointer;
if(currentPoint>0x600 && currentPoint<=0x6FF)//Means Arabic
{
basePointer = 0x0600;
}
if(currentPoint>0x900 && currentPoint<=0x97F)//Means Devnagri
{
basePointer = 0x0900;
}

OK, after thinking about this for a bit, here is a way to do it just using the Java API. It consists of three parts:
Regenerating the inaccessible block base table blockStarts in Character.UnicodeBlock into a Map
Using Character.UnicodeBlock.of(int) to look up the block name given the codepoint
Using the Map to lookup the Unicode block base given the block name
Note that regenerating the block base table is relatively slow at approx 10-15 ms on my machine, so it would probably be best to generate this once and reuse. I've left the rudimentary timing code in place.
private static final int SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE = 0x0F0000;
private static final int SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE = 0x100000;
private static final Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A =
Character.UnicodeBlock.of(SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE);
private static final Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B =
Character.UnicodeBlock.of(SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE);
public static Map<Character.UnicodeBlock, Integer> makeUnicodeBlockBaseMap() {
long startNanos = System.nanoTime();
Map<Character.UnicodeBlock, Integer> unicodeBases = new HashMap<>();
// Unicode blocks start on 16 (0x10) byte boundaries.
for (int cp = 0x00000; cp < SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE; cp += 0x10) {
Character.UnicodeBlock ucb = Character.UnicodeBlock.of(cp);
if (ucb != null) {
unicodeBases.putIfAbsent(ucb, cp);
}
}
// These blocks are huge, so add them manually.
unicodeBases.put(SUPPLEMENTARY_PRIVATE_USE_AREA_A, SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE);
unicodeBases.put(SUPPLEMENTARY_PRIVATE_USE_AREA_B, SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE);
long endNanos = System.nanoTime();
System.out.format("Total time = %.3f s%n", (endNanos - startNanos) / 1e9);
return unicodeBases;
}
public static void main(String[] args) {
Map<Character.UnicodeBlock, Integer> unicodeBlockBases = makeUnicodeBlockBaseMap();
String unicodeString = "कागज़";
int currentPoint = unicodeString.codePointAt(0);
Character.UnicodeBlock ucb = Character.UnicodeBlock.of(currentPoint);
System.out.println(ucb); // DEVANAGARI
System.out.format("0x%04X%n", unicodeBlockBases.get(ucb)); // 0x0900
}

You can put the start/end positions to SortedMaps for each language and check the codePoints:
private static final SortedSet<Integer, Integer> startToBase = new TreeMap<>();
private static final SortedSet<Integer, Integer> endToBase = TreeMap<>();
static {
// Fill the SortedMaps:
// latin
startToBase.put(0, 0);
endToBase.put(0x00ff, 0);
// ...
}
// Or load this from a web service, table or anything you find comfortable
public static final int baseCodePoint(int codePoint) {
// The codePoint should be inserted here (after)
int baseFromStart = startToBase.get(startToBase.headMap(codePoint + 1).lastKey());
// the code point should be inserted here (before).
int baseFromEnd = endToBase.get(endToBAse.tailMap(codePoint).firstKey());
if (baseFromStart == baseFromEnd) {
return baseFromStart;
}
throw new IllegalArgumentException(codePoint + " is unknown.");
}

This is what I have done, thanks to Gábor Bakos for inspiration:
TreeMap<Integer, Integer> languageCodePoints = new TreeMap<>();
languageCodePoints.put(0x0020, 0x007E);
languageCodePoints.put(0x00A0, 0x00FF);
languageCodePoints.put(0x0100, 0x017F);
languageCodePoints.put(0x0900, 0x097F); // Devanagri
// So on for all other languages, referred ISO/IEC 10646:2010
// for code points of present languages
In the function I used this only:
String unicodeString = "कागज़";
int currentPoint = unicodeString.codePointAt(0);
int startCodePoint = languageCodePoints.floorKey(currentPoint);
Now "startCodePoint = 0x900" which I really required. I think pretty simple way. :-P
Just one thing is that, I have to maintain "languageCodePoints" TreeMap for new language entries but far better than switch/if-else.
Thanks to all for such kind support. :-)

You can use bit manipulation to find the base pointers, something like this:
switch (codePoint & 0xffffff00) {
case 0x0600: // Arabic
case 0x0900: // Devnagri, though you might need to check it is below 0x97F
case 0x0000: // Latin
default: // Something else
}
Ah, sorry I think Armenian requires further processing, but hopefully the general idea is applicable for most of the languages.
public static int baseCodePoint(int codePoint) {
switch (codePoint & 0xffffff00) {
case 0x0900: if (codePoint < 0x0980) return 0x0900;
case 0x0500: if (codePoint >= 0x0530 && codePoint <= 0x058F) return 0x0530;
// case ...: other bases where it is not the real base
// Handling regular base pointers
default: return codePoint & 0xffffff00;
}
}

Related

How to re-use value in different functions?

I am programming a Study in MotiveWave, a program used for (day)trading. The study is its own class. (info about MotiveWave's SDK found here: https://www.motivewave.com/sdk/javadoc/overview-summary.html)
public class L_V2 extends com.motivewave.platform.sdk.study.Study
My study uses 2 different timeframes: the 1 hour and the 4 hour bars. Both are calculated in a different function. Otherwise formulated: both use a different dataseries, as shown in the code below.
I have two values, being calculated on the 4 hour timeframe, called 'ma9' and 'ma11' that I would like to use in an 'if'-statement on the 1 hour timeframe.
This is the code for the 4 hour timeframe. It simply calculates 2 moving averages
#Override
protected void calculateValues(DataContext ctx)
{
int maPeriodTF2 = getSettings().getInteger(MA_PERIOD_TF2);
int ma2PeriodTF2 = getSettings().getInteger(MA2_PERIOD_TF2);
//Object maInput = getSettings().getInput(MA_INPUT, Enums.BarInput.CLOSE);
BarSize barSizeTF2 = getSettings().getBarSize(MA_BARSIZE_TF2);
DataSeries series2 = ctx.getDataSeries(barSizeTF2);
StudyHeader header = getHeader();
boolean updates = getSettings().isBarUpdates() || (header != null && header.requiresBarUpdates());
// Calculate Moving Average for the Secondary Data Series
for(int i = 1; i < series2.size(); i++) {
if (series2.isComplete(i)) continue;
if (!updates && !series2.isBarComplete(i)) continue;
// MA TF2
Double ma9 = series2.ma(getSettings().getMAMethod(MA_METHOD_TF2), i, maPeriodTF2, getSettings().getInput(MA_INPUT_TF2));
Double ma11 = series2.ma(getSettings().getMAMethod(MA2_METHOD_TF2), i, ma2PeriodTF2, getSettings().getInput(MA2_INPUT_TF2));
series2.setDouble(i, Values.MA9_H4, ma9);
series2.setDouble(i, Values.MA11_H4, ma11);
}
// Invoke the parent method to run the "calculate" method below for the primary (chart) data series
super.calculateValues(ctx);
I would now like to use those 2 values, 'ma9' and 'ma11' in another function, on the 1 hour timeframe:
#Override
protected void calculate(int index, DataContext ctx)
DataSeries series=ctx.getDataSeries();
if (ma9 < ma11 && other conditions)
{ctx.signal(index, Signals.YOU_SHOULD_BUY, "This would be my buying signal", series.getClose(index));
}
How can I export the ma9 and the ma11 so they become 'global' and I can re-use them in this other function ?
Basically, the idea is to store somewhere the values or just pass them appropriately after being computed.
There is a java pattern based on singleton that allow you to store/retrieve values inside a class (using a collection : HashMap). Any values could be added,retried in any classes based on predefined (key,value) using the construction Singelton.getInstance() with HashMap standard operation (put, get).
Maybe this example could be useful.
import java.util.Hashtable;
class Singleton extends Hashtable<String, Object> {
private static final long serialVersionUID = 1L;
private static Singleton one_instance = null;
private Singleton() {
};
public static Singleton getInstance() {
one_instance = (one_instance == null) ? new Singleton() : one_instance;
return one_instance;
}
}
import java.util.Random;
public class Reuse {
public static void main(String[] args) {
Reuse r = new Reuse();
Compute c = r.new Compute();
Singleton.getInstance().put("r1", c.getRandom());
Singleton.getInstance().put("r2", c.getRandom());
Singleton.getInstance().put("n", c.getName());
System.out.println(Singleton.getInstance().get("r1"));//print random_number_1
System.out.println(Singleton.getInstance().get("r2"));//print random_number_2
System.out.println(Singleton.getInstance().get("n"));// print name (value for key n)
}
class Compute
{
public Double getRandom()
{
return new Random().nextDouble();
}
public String getName()
{
return "name";
}
}
}

What is the most efficient way to count the intersections between two sets (Java)?

Question Background
I am comparing two (at a time, actually many) text files, and I want to determine how similar they are. To do so, I have created small, overlapping groups of text from each file. I now want to determine the number of those groups from one file which are also from the other file.
I would prefer to use only Java 8 with no external libraries.
Attempts
These are my two fastest methods. The first contains a bunch of logic which allows it to stop if meeting the threshold is not possible with the remaining elements (this saves a bit of time in total, but of course executing the extra logic also takes time). The second is slower. It does not have those optimizations, actually determines the intersection rather than merely counting it, and uses a stream, which is quite new to me.
I have an integer threshold and dblThreshold (the same value cast to a double), which are the minimum percentage of the smaller file which must be shared to be of interest. Also, from my limited testing, it seems that writing all the logic for either set being larger is faster than calling the method again with reversed arguments.
public int numberShared(Set<String> sOne, Set<String> sTwo) {
int numFound = 0;
if (sOne.size() > sTwo.size()) {
int smallSize = sTwo.size();
int left = smallSize;
for (String item: sTwo) {
if (numFound < threshold && ((double)numFound + left < (dblThreshold) * smallSize)) {
break;
}
if (sOne.contains(item)) {
numFound++;
}
left--;
}
} else {
int smallSize = sOne.size();
int left = smallSize;
for (String item: sOne) {
if (numFound < threshold && ((double)numFound + left < (dblThreshold) * smallSize)) {
break;
}
if (sTwo.contains(item)) {
numFound++;
}
left--;
}
}
return numFound;
}
Second method:
public int numberShared(Set<String> sOne, Set<String> sTwo) {
if (sOne.size() < sTwo.size()) {
long numFound = sOne.parallelStream()
.filter(segment -> sTwo.contains(segment))
.collect(Collectors.counting());
return (int)numFound;
} else {
long numFound = sTwo.parallelStream()
.filter(segment -> sOne.contains(segment))
.collect(Collectors.counting());
return (int)numFound;
}
}
Any suggestions for improving upon these methods, or novel ideas and approaches to the problem are much appreciated!
Edit: I just realized that the first part of my threshold check (which seeks to eliminate, in some cases, the need for the second check with doubles) is incorrect. I will revise it as soon as possible.
If I understand you correctly, you have already determined which methods are fastest, but aren't sure how to implement your threshold-check when using Java 8 streams. Here's one way you could do that - though please note that it's hard for me to do much testing without having proper data and knowing what thresholds you're interested in, so take this simplified test case with a grain of salt (and adjust as necessary).
public class Sets {
private static final int NOT_ENOUGH_MATCHES = -1;
private static final String[] arrayOne = { "1", "2", "4", "9" };
private static final String[] arrayTwo = { "2", "3", "5", "7", "9" };
private static final Set<String> setOne = new HashSet<>();
private static final Set<String> setTwo = new HashSet<>();
public static void main(String[] ignoredArguments) {
setOne.addAll(Arrays.asList(arrayOne));
setTwo.addAll(Arrays.asList(arrayTwo));
boolean isFirstSmaller = setOne.size() < setTwo.size();
System.out.println("Number shared: " + (isFirstSmaller ?
numberShared(setOne, setTwo) : numberShared(setTwo, setOne)));
}
private static long numberShared(Set<String> smallerSet, Set<String> largerSet) {
SimpleBag bag = new SimpleBag(3, 0.5d, largerSet, smallerSet.size());
try {
smallerSet.forEach(eachItem -> bag.add(eachItem));
return bag.duplicateCount;
} catch (IllegalStateException exception) {
return NOT_ENOUGH_MATCHES;
}
}
public static class SimpleBag {
private Map<String, Boolean> items;
private int threshold;
private double fraction;
protected int duplicateCount = 0;
private int smallerSize;
private int numberLeft;
public SimpleBag(int aThreshold, double aFraction, Set<String> someStrings,
int otherSetSize) {
threshold = aThreshold;
fraction = aFraction;
items = new HashMap<>();
someStrings.forEach(eachString -> items.put(eachString, false));
smallerSize = otherSetSize;
numberLeft = otherSetSize;
}
public void add(String aString) {
Boolean value = items.get(aString);
boolean alreadyExists = value != null;
if (alreadyExists) {
duplicateCount++;
}
items.put(aString, alreadyExists);
numberLeft--;
if (cannotMeetThreshold()) {
throw new IllegalStateException("Can't meet threshold; stopping at "
+ duplicateCount + " duplicates");
}
}
public boolean cannotMeetThreshold() {
return duplicateCount < threshold
&& (duplicateCount + numberLeft < fraction * smallerSize);
}
}
}
So I've made a simplified "Bag-like" implementation that starts with the contents of the larger set mapped as keys to false values (since we know there's only one of each). Then we iterate over the smaller set, adding each item to the bag, and, if it's a duplicate, switching the value to true and keeping track of the duplicate count (I initially did a .count() at the end of .stream().allMatch(), but this'll suffice for your special case). After adding each item, we check whether we can't meet the threshold, in which case we throw an exception (arguably not the prettiest way to exit the .forEach(), but in this case it is an illegal state of sorts). Finally, we return the duplicate count, or -1 if we encountered the exception. In my little test, change 0.5d to 0.51d to see the difference.

Can a method in Java use variables declared earlier in the class without having to pass them as parameters?

for instance would this be valid?
public void backtrack()
{
char d = "d";//initialize a series of characters to represent looked for directions
char l = "l";
char t = "t";
char temp = " ";//not sure why i put this here
String j = DNA1;// create two strings to be used for indexing purposes
String k = DNA2;
int x = mat_hold[0].length;//goes to the last row
int e = mat_hold.length;//goes to the last column
char[][] mat_hold2 = mat_hold;
opt_path = mat_hold[x][e];//initialize the beginning of the path to be last element in the array
while(opt_path != mat_hold2[0][0];)//while the current index does not equal the first element in the array
{
if(opt_path = d)// if the element in d was obtained from the diagonal
{
DNA_seq1.insert(0,j[x]);//using the matrix location [x][e]take the element from the DNA sequence and insert it into the front of the array we are building
DNA_seq2.insert(0,k[e]);//ditto
DNA_align.insert(0,"|");//since they are the same in this case, insert a line to connect them
opt_path = mat_hold[x-1][e-1]//set the opt path to the diagonal value to be searched
}//since in this case it was taken from the diagonal, that means both letters were the same and so both letters at the given
//indexes are inserted into the newly constructed sequence
if(opt_path = l)
{
DNA_seq1.insert(0,"_");
DNA_seq2.insert(0,k[e]);
DNA_align.insert(0," ");
opt_path = mat_hold[x][e-1];
}
if(opt_path = t)
{
DNA_seq1.insert(0,j[x]);
DNA_seq2.insert(0,"_");
DNA_align.insert(0," ");
opt_path = mat_hold[x-1][e];
}
}
}
where DNA1, DNA2, Dna_seq1, Dna_seq2, mat_hold etc are all declared and constructed earlier in the class definition. or would i have to write all of these into the parameters being passed?
Use fields instead of local variables. Something like that:
public class YourClassName {
private static final String DNA_seq2 = null;
private Object DNA_seq1;
private Object DNA_align;
private char[][] mat_hold;
public void backtrack() {
char d = 'd';//initialize a series of characters to represent looked for directions
char l = 'l';
char t = 't';
char temp = ' ';//not sure why i put this here
// Rest of your method...
}
}
Actually, the definition order is irrelevant. Fields are available in any place of your class, regardless of where they are declared:
public class YourClassName {
public void backtrack() {
char d = 'd';//initialize a series of characters to represent looked for directions
char l = 'l';
char t = 't';
char temp = ' ';//not sure why i put this here
// Rest of your method... and it can use DNA_seq2, too, although
// it is declared below.
}
private static final String DNA_seq2 = null;
private Object DNA_seq1;
private Object DNA_align;
private char[][] mat_hold;
}
The order is relevant only for local variables.
However, it is surely the smallest of your problems if this code you posted is the real one you have...

Are there any tricks to reduce memory usage when storing String data type in hashmap?

I need to store value pair (word and number) in the Map.
I am trying to use TObjectIntHashMap from Trove library with char[] as the key, because I need to minimize the memory usage. But with this method, I can not get the value when I use get() method.
I guess I can not use primitive char array to store in a Map because hashcode issues.
I tried to use TCharArrayList but that takes much memory also.
I read in another stackoverflow question that similar with my purpose and have suggestion to use TLongIntHashMap , store encode values of String word in long data type. In this case my words may contains of latin characters or various other characters that appears in wikipedia collections, I do not know whether the Long is enough for encode or not.
I have tried using Trie data structure to store it, but I need to consider my performance also and choose the best for both memory usage and performance.
Do you have any idea or suggestion for this issue?
It sounds like the most compact way to store the data is to use a byte[] encoded in UTF-8 or similar. You can wrap this in your own class or write you own HashMap which allows byte[] as a key.
I would reconsider how much time it is worth spending to save some memory. If you are talking about a PC or Server, at minimum wage you need to save 1 GB for an hours work so if you are only looking to save 100 MB that's about 6 minutes including testing.
Write your own class that implements CharSequence, and write your own implementation of equals() and hashcode(). The implementation would also pre-allocate large shared char[] storage, and use bits of it at a time. (You can definitely incorporate #Peter Lawrey's excellent suggestion into this, too, and use byte[] storage.)
There's also an opportunity to do a 'soft intern()' using an LRU cache. I've noted where the cache would go.
Here's a simple demonstration of what I mean. Note that if you need heavily concurrent writes, you can try to improve the locking scheme below...
public final class CompactString implements CharSequence {
private final char[] _data;
private final int _offset;
private final int _length;
private final int _hashCode;
private static final Object _lock = new Object();
private static char[] _storage;
private static int _nextIndex;
private static final int LENGTH_THRESHOLD = 128;
private CompactString(char[] data, int offset, int length, int hashCode) {
_data = data; _offset = offset; _length = length; _hashCode = hashCode;
}
private static final CompactString EMPTY = new CompactString(new char[0], 0, 0, "".hashCode());
private static allocateStorage() {
synchronized (_lock) {
_storage = new char[1024];
_nextIndex = 0;
}
}
private static CompactString storeInShared(String value) {
synchronized (_lock) {
if (_nextIndex + value.length() > _storage.length) {
allocateStorage();
}
int start = _nextIndex;
// You would need to change this loop and length to do UTF encoding.
for (int i = 0; i < value.length(); ++i) {
_storage[_nextIndex++] = value.charAt(i);
}
return new CompactString(_storage, start, value.length(), value.hashCode());
}
}
static {
allocateStorage();
}
public static CompactString valueOf(String value) {
// You can implement a soft .intern-like solution here.
if (value == null) {
return null;
} else if (value.length() == 0) {
return EMPTY;
} else if (value.length() > LENGTH_THRESHOLD) {
// You would need to change .toCharArray() and length to do UTF encoding.
return new CompactString(value.toCharArray(), 0, value.length(), value.hashCode());
} else {
return storeInShared(value);
}
}
// left to reader: implement equals etc.
}

Looking to associate strings to ints in a cleaner/more efficient way

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;
}

Categories