I'm new to Java. I'm wondering what will be the best option to store 2D array with different type of data.
It will be table of countries, each has capital and is in cotinent. Then I have to store it this way:
ContinentID | Country name | Capital
What to choose?
You might want to consider making a Country class to hold this data, and then maintaining a list/array of instances of this class.
public class Country {
private int continentId;
private String name;
private String capital;
public Country(int continentId, String name, String capital) {
this.continentId = continentId;
this.name = name;
this.capital = capital;
}
// ...
}
You would then have something along the lines of
List<Country> countries = new ArrayList<Country>();
countries.add(new Country(123, "USA", "Washington DC"));
...
create a country class with the needed attributes, then create a list, type it as country:
list<Country> clist = new ArrayList<Country>();
or any list you want. Now just store country objects in the list.
If continent id is just a sequence and does not add any specific meaning, you might want to consider a HashMap with key as country name and value as Capital. If order is important, consider a LinkedHashMap.
If continent id does carry meaning, then you might want to consider moving all the variables to a class, say Country and hold it in a list. If you are planning to retrieve by country name and not iterate, you might want to consider storing the objects in a Hashmap, with key as your country name or capital or whatever suits your need. The reason for a HashMap and not a list is that membership check on a List gives linear performance as against a constant time access on a HashMap.
HashMap<Integer, HashMap<String, String>>();
Related
I am creating an application where I have to store all the departmental stores and want to cache it.
the hierarchy would be like:-
Country -> State -> City -> Area-> Stores
which data structure should I use So my application will work like if
I query for country and state, it should give me all the store
I query for country and state and city, it should give me all the stores in that area.
I just thought of Tree, but not able to convert this scenario into this data structure.
So just build the hierarchy, with each level containing a Map of the next level down:
class Store {
string name;
// other stuff
}
class Area {
string name;
Map<string, Store> stores;
// other stuff;
}
class City {
string name;
Map<string, Area> areas;
// other stuff
}
class State {
string name;
Map<string, City> cities;
// other stuff
}
class Country {
string name;
Map<string, State> states;
// other stuff
}
And you have a Map of countries at class scope:
Map<string, Country> countries;
If you want all the stores in a particular Country, State, and City, you first have to get a reference to the city:
Country country = countries[countryName];
State state = country.states[stateName];
City city = state.cities[cityName];
Now, for each area in the city, you visit each of the stores:
for (Map.Entry<String, Area> pair : city.areas.entrySet())
{
Area area = entry.getValue();
for (Map.Entry<String, Store> storePair : areas.stores.entrySet())
{
// Here, pair.getKey() is the store name
// and pair.getValue() is the Store object
}
}
This is really just a hierarchical tree implemented with nested dictionaries. Nothing fancy.
You state that you want to cache the information. If that is true, and you do not want to alter it, but only cache it, I would recommend to forego the tree idea and simply build two maps based on the key combinations you really need, i.e.:
one cache mapping a type 1 key (consisting of country and state) to a list of stores
one cache mapping a type 2 key (consisting of country, state and city) to a list of stores in the area
That is the point of a cache, really: You want to put all the logic (which store belongs to which combination of key values) into the construction of the cache (initial or on first request) and not start any kind of iteration every time you do a lookup.
I'm preparing for a Java exam and have one question that got me lots of tough time. Despite studying it hard I'm not able to find out what determines the order of the result.
Have a look, please:
class Country {
public enum Continent {
ASIA, EUROPE
}
String name;
Continent region;
public Country(String na, Continent reg) {
name = na;
region = reg;
}
public String getName() {
return name;
}
public Continent getRegion() {
return region;
}
}
public class OrderQuestion {
public static void main(String[] args) {
List<Country> couList = Arrays.asList(
new Country("Japan", Country.Continent.ASIA),
new Country("Italy", Country.Continent.EUROPE),
new Country("Germany", Country.Continent.EUROPE));
Map<Country.Continent, List<String>> regionNames = couList.stream()
.collect(Collectors.groupingBy(Country::getRegion,
Collectors.mapping(Country::getName, Collectors.toList())));
System.out.println(regionNames);
}
}
What is the result?
A. {EUROPE = [Italy, Germany], ASIA = [Japan]}
B. {ASIA = [Japan], EUROPE = [Italy, Germany]}
C. {EUROPE = [Germany, Italy], ASIA = [Japan]}
D. {EUROPE = [Germany], EUROPE = [Italy], ASIA = [Japan]}
and what most important what determines the specific result and not another?
We can eliminate D because keys in Map need to be unique which fails for EUROPE.
We can eliminate C because of order in [Germany, Italy]. Italy was placed before Germany in list, so it also has to be stored in that order in result list.
But how we should decide if we should eliminate B or A? Well, we cant.
Map doesn't guarantee specific order of key-value pairs. Some maps allow remembering order of placing key-value pairs like LinkedHashMap, some allow to order entries by keys like TreeMap, but this behaviour is not specified for Collectors.groupingBy.
It is confirmed by fact that this method is using HashMap, which orders key-value pairs based on hashCode() of key (Country.Continent enum here) and amount of pairs already held. Implementation of hashCode() for Enum is inherited from Object class which means it is based on memory location which can change for each time when we run JVM, so it is random value which prevents us from assuming any order (which confirms that it is unspecified).
So based on lack of specification about Map returned by groupingBy both orders of entries is possible so both A and B are possible answers.
Suppose I want to store phone numbers of persons. Which kind of collection should I use for key value pairs? And it should be helpful for searching. The name may get repeated, so there may be the same name having different phone numbers.
In case you want to use key value pair. Good choice is to use Map instead of collection.
So what should that map store ?
As far it goes for key. First thing you want to assure is that your key is unique to avoid collisions.
class Person {
long uniqueID;
String name;
String lastname;
}
So we will use the uniqueID of Person for key.
What about value ?
In this case is harder. As the single Person can have many phone numbers. But for simple task lest assume that a person can have only one phone number. Then what you look is
class PhoneNumberRegistry {
Map<Long,String> phoneRegistry = new HashMap<>();
}
Where the long is taken from person. When you deal with Maps, you should implement the hashCode and equals methods.
Then your registry could look like
class PhoneNumberRegistry {
Map<Person,String> phoneRegistry = new HashMap<>();
}
In case when you want to store more then one number for person, you will need to change the type of value in the map.
You can use Set<String> to store multiple numbers that will not duplicate. But to have full control you should introduce new type that not only store the number but also what king of that number is.
class PhoneNumberRegistry {
Map<Person,HashSet<String>> phoneRegistry = new HashMap<>();
}
But then you will have to solve various problems like, what phone number should i return ?
Your problem has different solutions. For example, I'll go with a LIST: List<Person>, where Person is a class like this:
public class Person{
private String name;
private List<String> phoneNumbers;
// ...
}
For collections searching/filtering I suggest Guava Collections2.filter method.
You should use this:
Hashtable<String, ArrayList<String>> addressbook = new Hashtable<>();
ArrayList<String> persons = new ArrayList<String>()
persons.add("Tom Butterfly");
persons.add("Maria Wanderlust");
addressbook.put("+0490301234567", persons);
addressbook.put("+0490301234560", persons);
Hashtable are save to not have empty elements, the ArrayList is fast in collect small elements. Know that multiple persons with different names may have same numbers.
Know that 2 persons can have the same number and the same Name!
String name = "Tom Butterfly";
String[] array = addressbook.keySet().toArray(new String[] {});
int firstElement = Collections.binarySearch(Arrays.asList(array),
name, new Comparator<String>() {
#Override
public int compare(String top, String bottom) {
if (addressbook.get(top).contains(bottom)) {
return 0;
}
return -1;
}
});
System.out.println("Number is " + array[firstElement]);
Maybe
List<Pair<String, String> (for one number per person)
or
List<Pair<String, String[]> (for multiple numbers per person)
will fit your needs.
Is there a collection object or a approach to hold a combination of elements?
For instance, I need to create a list that contains the combination of the elements name, age, height and weight.
Creating an object for this is not a good idea in my case. Because the number of fields keep changing.
I need to create this list to pass to a query.
Any solution?
class MyContainer {
String someString;
int someInt;
}
List <MyContainer> myList = new List<>();
Something like that!?
I donĀ“t know exactly, what you mean by "Creating an object for this is not a good idea in my case". You could as an alternative create a List<Object> and put in whatever you have or even a List<List<Object>> if you want to have a List of a number of grouped objects.
The best approach would be to make an Object with all the possible elements in it.
class myObject {
String name;
Integer age;
Float weight;
// Etc
}
Or have a base class then have another class which extends this with additional elements
class myExtendedObject extends myObject{
String streetAddress;
String city;
// etc;
}
Then if you don't have an element set it to null... you could always build your query from the object itself by including a method to return your query, juct check if its null and not include in your query (Assuming you mean an sql style query)
public String buildQuery{
String query = "Select * from blahtable Where ";
query += (name != null)?" name = " + name : "";
// etc, or what ever your query needs to be
return query
}
Other wise you could just have a method which returns a map of your elements then you know what the type of each element is based on the key
public Map<String, Object> getElements{
Map<String, Object> myMap = new HashMap<String, Object>();
if(name != null)
myMap.put("Name", name);
// etc
return myMap
}
What about just using a Map for that and use attribute name as key (e.g. Weight )?
You can use any combination of attributes you want and it would be convenient to pass such collection to the query
Consider Enum map should you require more column names type safety
Basically, I have an arraylist declared like :
private ArrayList<HashMap<String, String>> songsList =
new ArrayList<HashMap<String, String>>();
now what I want to do is that for each key I want to give two value fields. Can it be done??
Secondly I want to sort the key-value pair according to the value pair. So how can it be achieved?
That's a lot of String objects. Have you considered encapsulating your data structure using an Object, rather than a complex collection of strings? For example, assuming your map key is a song:
public Song implements Comparable<Song> {
private String title;
private String artist;
private String album;
public Song(String title, String artist, String album) {
...
}
public int compareTo(Song s) {
// sorting logic
}
... // getters, setters, equals & hashCode
}
Then, create your list of songs:
List<Song> songs = new ArrayList<Song>();
songs.add(new Song("Dancing Queen", "Abba", "Arrival"); // I had to find this on Wikipedia
...
Then sort them:
Collections.sort(songs);
You can implement the comparable interface for the sorting problem of yours. And for having multiple values for a value in a map, create a class with the required values with getters and setters. And use the class as a value against the key.