In the instructions I have been asked to "declare a interface type to hold a map with sets of characters as its keys, and with sorted sets of strings as values". All this time I have been using TreeSets. Now I am not sure, I am now
thinking of using TreeMap. Code below is demo TreeMap I have used. Firstly is it acceptable to use TreeSet instead of TreeMap as per instruction above. Secondly I am getting an error "non-static variable names cannot be referenced from a static context", when using TreeMap for methodB()? Thanks.
public class MyMates
{
private TreeMap names = new TreeMap();
private static String[] name1 = null;
private static String[] name2 = null;
private static String[] name3 = null;
public MyMates()
{
super();
names = new TreeMap();
}
public static void methodASet()
{
String[] name1 = new String[] {"Amy", "Jose", "Jeremy", "Alice", "Patrick"};
String[] name2 = new String[] { "Alan", "Amy", "Jeremy", "Helen", "Alexi"};
String[] name3 = new String[] { "Adel", "Aaron", "Amy", "James", "Alice" };
}
public static String methodB(String aTemp)
{
for (int i = 0; i < name1.length; i++)
{
names.add(name1[i]);
}
System.out.println(names);
for (int i = 0; i < name2.length; i++)
{
names.add(name2[i]);
}
System.out.println(names);
for (int i = 0; i < name3.length; i++)
{
names.add(name3[i]);
}
System.out.println(names);
return aTemp
}
public static void populateTable()
{
girlFriends myList = new girlFriends();
names.addAll(myList.getNames()); // same error here
}
As R. Bemrose said in a comment, you're not being asked for an implementation, just an interface. So don't worry about the implementation. A map lets you put a value (in your case, a sorted set of Strings) in for a particular key (in your case, a set of characters), and use the same key to retrieve the same value. What would that interface look like? That's the question.
The "non-static variable names cannot be referenced from a static context" is easy to resolve.
You can remove the "static" modifier of your methodB().
Another solution is to declare your class member "names" as static.
Your method methodASet() has a bug !!! You redeclare name1, name2, and name3 as local variables. So the static class members are never set.
A TreeSet and a TreeMap haven't the same function :
A TreeMap is a Map (inteface java.util.Map), that is to say an association key/value (where keys are ordered)
A TreeSet is a Set (interface java.util.Set) : an ordered collection of objects where all objects are unique in the set, without the "key" notion of the Map.
So, you have to choose the representation (Map or Set) in relation with your needs (access to the objects by a key or not).
It looks like private TreeMap names isn't static so it can't be accessed from a static method. Perhaps you need to brush up on your static variables/methods? http://leepoint.net/notes-java/flow/methods/50static-methods.html
You have to remember that methodASet and methodB are different methods and variables in methodASet cannot be seen by methodB. When you declare String[] name1 you're making a new variable of type String[], not using the class variable name1 (the one you set to null). Remove the "String[]" from the variables in methodASet to reuse the class variables.
Thinking about it, does TreeMap even have add() methods? I think you might want to switch to the aforementioned TreeSet or change your add() methods to put().
For populateTable(), are you sure that girlFriends is a type? Where is it coming from? Are you sure you don't mean for myList to be of a standard java collections type?
Hope my (mostly convoluted) post helps!
Edit: Blast! I think you're right. It looks like he's only got to write the interface, not the implementation.
Edit: Static examples
Static method:
Class.doSomething()
Static variable:
Class.count_something
Class method:
ObjectType obj = new ObjectType()
obj.doSomething()
Class variable:
ObjectType obj = new ObjectType()
obj.count_something
This is kind of an aside since it looks like your instructions actually want you to create an interface, not an implementation. However, given the task of implementing this interface, if consistently using Java terminology (map, set, character and string), the instructions seem to want you to maintain this data structure:
Map<Set<Character>, SortedSet<String>> map;
If that's the case, a TreeMap is not a good choice of implementation since it is very difficult to enforce an ordering on non-sorted Sets. Set doesn't implement Comparable for starters and creating a Comparator for your TreeMap would require some complex logic.
If the above is what your instructor is expecting, I would suggest using a HashMap which has no problem using a Set as a key type:
map = new HashMap<Set<Character>, SortedSet<String>>();
Related
I would like to create an array that stores the names (String) and values (integer) of company stocks, but I don't know how to go about it.
An Object[] can hold both String and Integer objects. Here's a simple example:
Object[] mixed = new Object[2];
mixed[0] = "Hi Mum";
mixed[1] = Integer.valueOf(42);
...
String message = (String) mixed[0];
Integer answer = (Integer) mixed[1];
However, if you put use an Object[] like this, you will typically need to use instanceof and / or type casts when accessing the elements.
Any design that routinely involves instanceof and/or type casts needs to be treated with suspicion. In most cases, there is a better (more object-oriented, more efficient, less fragile) way of achieving the same ends.
In your particular use-case, it sounds like what you really need is a mapping object that maps from String (names) to Integer (numbers of stocks). And the nice thing about Java is that there are existing library classes that provide this functionality; e.g. the HashMap<K,V> class, with String as the key type and Integer as the value type.
Another possibility might be an array, List or Set of some custom or generic pair class. These have different semantic properties to Map types.
You have two choices:
Use an array.
public class Value {
public String name;
public int number;
}
...
public Value[] values = new Value[10];
....
Use a map which has much more comfort, specially you can use the name as key to get a value
....
public Map<String, int> valueMap = new HashMap<String,int>();
valueMap.put("Sample",10);
int value = valueMap.get("Sample");
...
You can use a Map data structure instead of an array. This is basically a type of Collection that has key-value pairs. Your string name can be used as the key and the value is your integer.
Map<String,Integer> myMap = new HashMap<String, Integer>;
MyMap.put("someone", 6);
Note that using a HashMap has a speed advantage over an array during lookup. The complexity of HashMap lookup is O(log(n)) while that of an array is O(n).
I have two arrays of predefined length, let us say 8, which contains related data. I can arrange them in such a way that array1[0] has corresonding mapping at array2[0]. That is key value pairs are at the same index in both arrays. In such a case, for iterating the array, I can either use a for loop like below
for(int i=0;i<array1.length;i++){
int array1Val = array1[i];
String array2Val = array2[i];
//some code
}
Is this approach gud? Or is it better to use linked hashmap instead and loop using
map.entrySet()
Complexity wise and efficiency wise which is a better approach?
Rule of thumb: When you are considering creating corresponding arrays, then it's time to create a class for that corresponding data, and create an array of that class. This is the clearest, most readable, object-oriented way to store your corresponding data in objects in Java. (It doesn't have to be called "Data".)
class Data {
private int value1;
private String value2;
// Any other arrays? Make another value here.
// Constructor, getters, setters
}
Then declare an array of that class, and store objects in it here.
Data[] mydata = new Data[length];
for (int i = 0; i < length; i++) {
mydata[i] = new Data(); // and you can then initialize the Data object too.
}
Then one for loop can access each Data object.
for (int i = 0; i < length; i++) {
Data data = mydata[i];
// Extract values here.
}
(Or you can use the enhanced "foreach" loop also.)
for (Data data : mydata) {
// Extract values here.
}
Use a map.
In terms of performance, you are iterating over the length of the data structure.
so its only o(n)
reading from a map is o(1), reading from an array is also o(1)
so really no difference in performance.
But in terms of readability and maintainability its better to have a single "map" data structure then two array data structures that need to be consumed/used in a "special way" (in this case you need to remember that array1[0] maps to array2[0]. That makes the code less readable and more complicated than it has to be.
Keep your code clean, easy to read, and simple, use a map:
Here is are ways to loop thru a map in java:
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
}
for (Object value : map.values()) {
// ...
}
[UPDATE]
In response to people who suggest "hey create a Class"...
Please ask yourself "who needs to consume this data"?
If the data is only relevant to an internal method, then I suggest using an anonymous class like here:
public void myMethod(String param1, String param2) {
class MyAnonymousClass {
String data1;
String data2;
}
MyAnonymousClass anonymous = new MyAnonymousClass();
anonymous.data1 = param1;
anonymous.data2 = param2;
}
If the data is only relevant to the internals of another Class then create a private static inner class.
pubic class SomeClass {
private static class MyDataContainer {
}
}
Just be aware of these choices when creating classes.
Cheers!
I am new to java and practicing by creating a simplistic NaiveBayes classifier. I am still new to object instantiation, and wonder what to do to initialize a HashMap of HashMaps. When inserting new observations into the classifier, I can create a new HashMap for an unseen feature name in a given class, but do I need to initialize?
import java.util.HashMap;
public class NaiveBayes {
private HashMap<String, Integer> class_counts;
private HashMap<String, HashMap<String, Integer>> class_feature_counts;
public NaiveBayes() {
class_counts = new HashMap<String, Integer>();
// do I need to initialize class_feature_counts?
}
public void insert() {
// todo
// I think I can create new hashmaps on the fly here for class_feature_counts
}
public String classify() {
// stub
return "";
}
// Naive Scoring:
// p( c | f_1, ... f_n) =~ p(c) * p(f_1|c) ... * p(f_n|c)
private double get_score(String category, HashMap features) {
// stub
return 0.0;
}
public static void main(String[] args) {
NaiveBayes bayes = new NaiveBayes();
// todo
}
}
Note this question is not specific to Naive Bayes classifiers, just thought I would provide some context.
Yes, you need to initialize it.
class_feature_counts = new HashMap<String, HashMap<String, Integer>>();
When you want to add a value to class_feature_counts, you need to instantiate it too:
HashMap<String, Integer> val = new HashMap<String, Integer>();
// Do what you want to do with val
class_feature_counts.put("myKey", val);
Recursive generic data structures, like maps of maps, while not an outright bad idea, are often indicative of something you could refactor - the inner map often could be a first order object (with named fields or an internal map), rather than simply a map. You'll still have to initialize these inner objects, but it often is a much cleaner, clearer way to develop.
For instance, if you have a Map<A,Map<B,C>> you're often really storing a map of A to Thing, but the way Thing is being stored is coincidentally a map. You'll often find it cleaner and easier to hide the fact that Thing is a map, and instead store a mapping of Map<A,Thing> where thing is defined as:
public class Thing {
// Map is guaranteed to be initialized if a Thing exists
private Map<B,C> data = new Map<B,C>();
// operations on data, like get and put
// now can have sanity checks you couldn't enforce when the map was public
}
Also, look into Guava's Mulitmap/Multiset utilities, they're very useful for cases like this, in particular they do the inner-object initializations automatically. Of note for your case, just about any time you implement Map<E, Integer> you really want a Guava Multiset. Cleaner and clearer.
You must create an object before using it via a reference variable. It doesn't matter how complex that object is. You aren't required to initialize it in the constructor, although that is the most common case. Depending on your needs, you might want to use "lazy initialization" instead.
Do not declare your variables with HashMap. It's too limiting.
Yes, you need to initialize class_feature_counts. You'll be adding entries to it, so it has to be a valid map. In fact, initialize both at declaration and not in the constructor since there is only one way for each to start. I hope you're using Java 7 by now; it's simpler this way.
private Map< String, Integer> classCounts = new HashMap<>();
private Map< String, Map< String, Integer>> classFeatureCounts = new HashMap<>();
The compiler will deduce the types from the <>. Also, I changed the variable names to standard Java camel-case style. Are classCounts and classFeatureCounts connected?
The title is probably not the best, I apologize for that.
I have several final static Lists I am using to define defaults for database values. The default list of values should never change, as such when populating them, I use Collections.nCopies(int,T) to obtain an immutable List. These Lists are then used to populate lists in another class with defaults. The values in these Lists are expected to change.
Pseudocode for the class of defaults:
public final class FooDefaults {
public final static List<Integer> LIST_ONE;
public final static List<String> LIST_TWO;
//This map allows easier access to "column" values.
public final static List<Map<String,String>> LIST_THREE;
static {
LIST_ONE = Collections.nCopies(7, 5);
LIST_TWO = Collections.nCopies(10, "boo");
Map<String, String> temp = new java.util.LinkedHashMap<>();
for(int i=0;i<15;i++) {
temp.put(("Param"+i),"foo");
}
LIST_THREE = Collections.nCopies(10, temp);
}
}
Pseudocode for the class of editable values:
public class Foo {
//Keep the reference from changing.
//Prevents an accidental new.
private final List<Integer> listOne;
private final List<String> listTwo;
private final List<Map<String,String>> listThree;
public Foo() {
listOne = new java.util.ArrayList<>(FooDefaults.listOne);
listTwo = new java.util.ArrayList<>(FooDefaults.listTwo);
listThree = new java.util.ArrayList<>(FooDefaults.listThree);
}
}
My concern is that as I have performed a shallow copy on these lists, changes in the lists in Foo, will be visible in the Lists in FooDefaults.
This post: https://stackoverflow.com/a/1685158/1391956 suggests that due to Strings and Integers being immutable, I need not worry about accidentally overwriting the values in FooDefaults.LIST_ONE and FooDefaults.LIST_TWO.
Thus, my primary concern are the values contained within the maps in FooDefaults.LIST_THREE. If I change the values in the maps in Foo's listThree, will the change be visible in FooDefaults?
If so, what would be the most efficient way to handle this? Class Foo is likely to be instantiated over a thousand times and added to a List in another class, thus speed will potentially be an issue.
I originally created the final static lists in FooDefaults in the interest of speed, as it is my (probably incorrect) assumption that creating those Lists in FooDefaults and simply copying the data would be faster than creating them every time Foo is instantiated.
EDIT: If I must perform a Deep Copy I plan on using something similar to:
public static final List<Map<String, String>> getListThreeCopy() {
Map<String,String> temp = new java.util.LinkedHashMap<>();
for(Map.Entry<String, String> entry: LIST_THREE.get(0).entrySet()) {
temp.put(entry.getKey(),entry.getValue());
}
List<Map<String,String>> rtnList = new java.util.ArrayList<>();
for(int i=0;i<LIST_THREE.size();i++) {
rtnList.add(temp);
}
return rtnList;
}
Would there be a faster way?
In the end, I used the code mentioned at the end of my post in a loop to perform a Deep Copy 1,500 times and timed it. I did the same with the instantiation code.
As I somewhat expected, recreating the List from scratch is much faster than a deep copy.
16 milliseconds with the Deep Copy versus 0 milliseconds with instantiation. I timed it using System.currentTimeMillis().
So long as I only create it in a static function, I have little reason to worry about errors.
I want to convert a List to a List so that each object on my new list includes the first element of each String[].
Do you know if this is possible to do in java?
for example:
public List<String[]> readFile(){
String[]array1={"A","1.3","2.4","2.3"};
String[]array2={"B","1.43","3.4","2.8"};
String[]array3={"C","5.23","2.45","2.9"};
List<String[]>ReadFile= new ArrayList<String[]>();
ReadFile.add(array1);
ReadFile.add(array2);
ReadFile.add(array3);
return ReadFile;
}
Now I want a method which will take the List ReadFile from above to somehow split the arrays of strings into an ID which will be the first element "A", "B", "C" and another part which would be the string array of numbers which I will put through another method to convert numbers from String to type Double. I have already got the method to convert to double but I need to be able to keep track of the ID field because the ID field will be used to identify the array of numbers.
A friend suggested that I create an Object where each objects has one part as a String ID and the other part as an array. That is the part which I do not know how to do.
Can anybody help please?
below is the method declaration which I believe I should have so the return type will be List where each array has been converted to an Object with two parts.
public List<Object> CreateObject(List<String[]>ReadFile){
}
Thanks,
Jetnori.
Hi all, Thank you for taking your time to help.
I can see the benefit of using HashTables. I am as of now trying to implement it. I know i might be sidetracking a little but just to explain what I am trying to do:
In my project I have CSV file with data about gene expression levels. The method that I use from OpenCSV to read the file returns a List(String[]) where each String[] is one row in the file. The first element of each row is variable name (recA, ybjE etc). The rest of the row will be numbers data related to that variable. I want to calculate Pearson's correlation between each of the number arrays. The method which I have got implemented already does that for me but the problem that I have now is that I had to remove the string values from my arrays before I could convert to double by iterating over the array. After I have managed to calculate the correlation between each array of doubles by still keeping the ID linked to the row, I want to be able to draw an undirected node graph between the genes that have a correlation higher than a threshold which I will set (for example correlation higher than 0.80). I don't know if i am biting more than i can chew but I have 30 days to do it and I believe that with the help of people like you guys I will get through it.
Sorry for going on for a bit.
thanks,
Jetnori.
I agree with the answer Alb provided, however this is what your friend has suggested, first you need a class to represent the data. I have included a constructor that parses the data and one that accepts already parsed data, depending on how you like to think of things.
public class NumberList {
private double[] numbers;
private String key;
public NumberList(Strig key, double[] numbers){
this.ley = key;
this.numbers = numbers;
}
public NumberList(String[] inputList) {
key = inputList[0];
numbers = new double[inputList.length-1];
for(int i=1;i<inputList.length;i++){
numers[i-1] = Double.parseDouble(inputList[i]);
}
}
public String getKey() {
return key;
}
public double[] getNumbers() {
return numbers;
}
}
Then you need your function to generate the list:
public List<NumberList> CreateObject(List<String[]> ReadFile){
ArrayList<NumberList> returnList = new ArrayList<NumberList>(ReadFile.size());
for (String[] input : ReadFile) {
returnList.add(new NumberList(input));
}
return returnList;
}
Note this uses the constructor that parses the data, if you use the other constructor then the "CreateObject" function would need to include the parsing logic.
Finally on a side note the standard convention in java is that the only thing that is capitalized are class names and final static fields (which appear in all caps sepearted by underscores), so conventionally the method signature would be:
public List<NumberList> createObject(List<String[]> readFile){
...
}
Sounds like you need a Map instead of a List, it lets you index things by a key (in your case ID).
Map<String, String[]> map = new Hashmap<String, String[]>();
for( String[] array : ReadFile ){
map.put( array[0], array );
}
then to get the array of values for 'A' you would do:
String[] values = map.get( "a" );
If you want the values to be doubles instead of strings you'll want to change the array before putting it (the map.put call) I'd advise using a list or other collections instead of an array also. You also will probably also want to remove the ID part from these values, which my code does not do.
public class Split_ListwithIDs {
Hashtable<String, String[]> table = new Hashtable<String, String[]>();
Splitter spl ;
public Split_ListwithIDs(Splitter split){
spl = split;
}
private void addEntry(String key , String[] vals){
table.put(key, vals);
}
public void parseList(List<String[]> list){
for(String[] entry : list){
String[] temp = new String[entry.length - 1];
System.arraycopy(entry, 1, temp, 0,entry.length - 1);
addEntry(entry[0], spl.GetStringArrayOfNumbers(temp));
}
}
class SplittingHelper implements Splitter{
#Override
public String[] GetStringArrayOfNumbers(String[] arr) {
String[] strArray = null ;
// implementation here
return arr;
}
}
interface Splitter {
String[] GetStringArrayOfNumbers(String[] arr);
}
}
You will have to use a Hashtable instead of a list of objects.( I am assuming that you will need to search through the list for a given entry using the First alphabet as key - This will be very laborious if you want to use a List ).
In the method SplittingHelper , provide your custom logic to parse the string of numbers and return another string[] of numbers.
I don't understand your goal, but for 'an object with 2 parts' you might consider storing them in a Hashtable: http://download.oracle.com/javase/6/docs/api/java/util/Hashtable.html