Creating unlimited dictionaries or lists - java

I need to get user input to either create lists, tuples, hashtables, etc. for ordered or key keeping. For example in python it would look like this when completed:
all = {'main1':{'name':'Hannag', 'birth':'date1', 'gender':'female'}, 'main2':{'name':'Kate', 'birth':'date2', 'gender':'female'}, 'main3':{'name':'Ben', 'birth':'date3', 'gender':'male'}}
In java I haven't figured out how to create a string key with more string keys inside of it. main1':{'name':'Hannag', 'birth':'date1', 'gender':'female'}
I've tried using tuples, but you can only do a set number from I what I've tried using tuple3.
Map<String, Tuple3<String, String, String>> dos = new HashMap<String, Tuple3<String, String, String>>();
while(adds.contains(contin))
{
String li = input.nextLine();
String fName = input.nextLine();
String fDir = input.nextLine();
do.Add(fName, new Tuple3((String) li, (String) fName, (String) fDir));
I also tried using hashtable inside hashtable, but hashtable titles can't be strings. I need the names of hashtables or lists etc to be strings. Is there any way I could pull this off?

Instead of messing around with tuples and maps, create a class:
class Person {
final String name;
final String birth; // maybe make this a Date?
final String gender; // if you subscribe to the gender binary, maybe make this an enum?
Person(String name, String birth, String gender) { // constructor
this.name = name;
this.birth = birth;
this.gender = gender;
}
}
and then have a
Map<String, Person> map = new HashMap<>();
map.put("main1", new Person("Hannag", "date1", "female"));
...

Related

Match Java Map keyset values with String values of a Java list of objects

I have a Java list of objects which each one contains a String value (code). Also I have a Java Map. I want to check whether all the elements in the Map keys are included in the list of the String values.
The Model class :
public class Obj {
private String code;
private String name;
private String uom;
public Obj(String code, String name, String uom) {
this.code = code;
this.name = name;
this.uom = uom;
}
}
the implemention :
private static final Obj weight = new Obj("weight", "Weight", "Kg");
private static final Obj height = new Obj("height", "Height", "cm");
public static final List<Obj> objMasters = List.of(weight, height);
Set<String> keySet = map.keySet(); // returns the keyset values from the Map
boolean match =objMasters.stream()
.anyMatch(objMaster -> objMaster.getCode().matches(keySet.toString()));
But with this implementation I always get false as the value for the match. What has gone wrong here?
From what I now understood about your question, try this.
List<String> codes = objMasters.stream().map(obj -> obj.getCode()).collect(Collectors.toList());
boolean match = codes.containsAll(keySet);
0,when you use collection or map,please override equals and hashCode methods
/n1,you can deep study of source code like get() contain() and others methods
/n2, by then you will undunderstand why

How to initialise a Map<K, Map<K,V>> on a single line

Is it possible to combine these two lines of code into one?
allPeople.put("Me", new HashMap<String, String>());
allPeople.get("Me").put("Name", "Surname");
The literal replacement of these two lines would be (in Java 8+):
allPeople.compute("Me", (k, v) -> new HashMap<>()).put("Name", "Surname");
or, in the style of Bax's answer, for pre-Java 9, you could use:
allPeople.put("Me", new HashMap<>(Collections.singletonMap("Name", "Surname")));
Starting with Java 9 there is a JDK provided Map factory
allPeople.put("Me", Map.of("Name", "Surname"));
You should probably represent a person as an object. That way you cannot call get("someKey") on a key that does not exist and your code blow up. That is the idea of object oriented programming. To encapsulate related data and functionality. Nested maps does a similar thing, but it is more error prone. For a language that does not support objects, that makes sense. But representing a person as an object allows you to better control the fields the mapping has, thus making your code more error-free.
class Person {
private String name;
private String surname;
public Person(String name, String surname) {
this.name = name;
this.surname = surname;
}
}
Then you create a map that maps names to people:
Map<String, Person> allPeople = new HashMap<>();
// Create an object that represents a person
Person me = new Person("name", "surname");
// Map the string "me" to the object me that represents me
allPeople.put("ME", me);

Parsing file and sort lines by property

So basically someone gave me a text file for me to read through Java and I have to print out certain parts of it.
So what I did was I put all of the text file into a String and between every word there's a ":". So i split all of the text with ":" using split function. At first every line looks like this
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
firstName:Surname:Age:Country
After it would be the same thing without the colons.
So now if I say all[0], I would get all the firstNames only.
What I'm trying to get is get the top 3 highest ages but I do not know how to do that.
Explanation
Suppose you have a file with lines like
John:Doe:20:USA
Jane:Doe:35:Germany
Robert:Moe:14:Japan
Larry:Loe:25:China
Richard:Roe:27:India
and you want the 3 lines with the highest age, that would be
Jane:Doe:35:Germany
Richard:Roe:27:India
Larry:Loe:25:China
The procedure is straightforward. First read all lines, split by : and parse the data into a wrapper class like Person. Collect them into some collection like List<Person> and sort them using a Comparator that compares the age. Alternatively you could let Person implement Comparable and then use their natural order.
If efficiency matters you can also do partial sort since you are only interested in the top 3 hits. For this you could use a PriorityQueue, insert all elements and call poll three times.
Solution
First the Person wrapper class
public class Person {
private String mFirstName;
private String mSurname;
private int mAge;
private String mCountry;
public Person(String firstName, String surname, int age, String country) {
this.mFirstName = firstName;
this.mSurname = surname;
this.mAge = age;
this.mCountry = country;
}
// TODO Some getters
public String toString() {
return this.mFirstName + ":" + this.mSurname
+ ":" + this.mAge + ":" + this.mCountry;
}
public static Person parse(String[] data) {
String firstName = data[0];
String surname = data[1];
int age = Integer.parseInt(data[2]);
String country = data[3];
return new Person(firstName, surname, age, country);
}
}
Next we read all lines, split the data and parse them into Person. After that we sort and limit the result to 3. Finally we collect to a List and print the results.
Path file = Paths.get(...);
Pattern separator = Pattern.compile(":");
List<Person> persons = Files.lines(file) // Stream<String>
.map(separator::splitAsStream) // Stream<String[]>
.map(Person::parse) // Stream<Person>
.sorted(Comparator.comparingInt(Person::getAge).reversed())
.limit(3)
.collect(Collectors.toList());
persons.forEach(System.out::println);
Or if you want to use the PriorityQueue as suggested, which will improve runtime:
Path file = Paths.get(...);
Pattern separator = Pattern.compile(":");
PriorityQueue<Person> personQueue = Files.lines(file)
.map(separator::splitAsStream)
.map(Person::parse)
.collect(Collectors.toCollection(() -> {
return new PriorityQueue<>(
Comparator.comparingInt(Person::getAge).reversed());
}));
List<Person> persons = new ArrayList<>(3);
persons.add(personQueue.poll());
persons.add(personQueue.poll());
persons.add(personQueue.poll());
persons.forEach(System.out::println);

A data structure similar to a HashMap with more than one "distinct" value

Is there any similar data structure that stores a key and unlike a HashMap<Key, Value> it stores more value regarded to a single key? If not, any suggestion for doing so? Because making several HashMap with same key and different values does not look so neat.
EDIT
When I said more than one value, I mean distinct value. For example, consider a map that has a key for each person and we wish to store persons Name and address and phone number.
Based on your edit you probably want to still store a single Value for each Key but make the value an Object. For example
public class PersonInfo {
private String name;
private String address;
private String phoneNumber;
etc...
}
and define your map as HashMap<Key, PersonInfo>
Check Guava's Multimap ! It let you have multiple values for the same key.
Example
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("Fruits", "Banana");
multimap.put("Fruits", "Apple");
multimap.put("Fruits", "Pear");
multimap.put("Vegetables", "Carrot");
// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
Guava is a really useful library for java programmer you should definitely check it out !
Edit
Well after you edit you really just need a simple HashMap<Key, Person>. You can define your Person class like this:
public class Person {
private String name;
private String address;
private String phoneNumber;
public Person(String name, String address, String phoneNumber) {
this.name = name;
this.address = address;
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
Use your HashMap<Key, Person> where Key could be a String for example:
Map<String, Person> personMap = new HashMap<String, Person>();
personMap.put("patrick_key", new Person("Patrick", "1000 Notre-Dame street", "123456789"));
personMap.put("stephan_key", new Person("Stephan", "2000 Notre-Dame street", "987654321"));
then you can access Patrick like that:
Person person = personMap.get("patrick_key");
Use a hashmap and each "value" is a list (linked or double linked on the basis of your needs).
A simple solution to this is to create some form of PersonInfo object, then map that value along with the key String. When you want to call the distinct key, you can just retrieve the object which contains any value you wish to describe about that person.
If you then want them to be distinct, you can record each phone number on a separate list and any time the user inputs a number, you can just check it against the global list of numbers.
(address/name's can be used twice because they're fairly common ie. think Junior and Senior living in the same home)

How to create an associative list in Java?

I am trying to have a user enter a String to search for a value in a list. This works fine, but I also want the String to have a numeric value. This way I can get the certain item in the lists price. I tried:
public List<String, double>
However this always gives me an error. How can I store strings and their corresponding numeric value?
Use a Map.
Map<String, Double> someMap = new HashMap<String, Double>();
Then, you can use Map#put(K, V) and Map#get(K) to put and get values.
Check out the Map documentation as well.
From Java 7 onwards, you can omit the generic type within the constructor's declaration:
Map<String, Double> someMap = new HashMap<>();
Are you only storing a String and a Double, or will you eventually need to store more information about each object?
For example, you're talking about storing a name and a price. If this is for a shopping-like program, you would probably be best to store all the information for each product in a new class, and then store the class in the HashMap. For example..
// Class for your product and all related information...
public class Product {
String name;
double price;
String color;
double weight;
public Product(String name, double price, String color, double weight){
this.name = name;
this.price = price;
this.color = color;
this.weight = weight;
}
}
// Now add each Product to a HashMap (in your main class)...
HashMap<String,Product> products = new HashMap<String,Product>();
products.put("Cheese", new Product("Cheese",1.10,"Yellow",0.5);
products.put("Milk", new Product("Milk",2.0,"White",1.5);
You will then be able to query the HashMap for "Cheese" and you'll get the Product and and all the information for it...
Product cheese = products.get("Cheese");
double price = cheese.getPrice();

Categories

Resources