I just did a company online and i couldnt get this question right..
looking to improve for next online assessment.
question is:
your given 1 input string where the format is like this:
current:target
where current = Company,Stock or Bond,amount
and target = Company,Stock or Bond,amount
and the ':' separates current and target
an example is:
Vodafone,STOCK,10|Google,STOCK,15|Microsoft,BOND,15:Vodafone,STOCK,15|Google,STOCK,10|Microsoft,BOND,15
the output should be a string that makes the input meet the output for this case its going to be:
SELL,Google,STOCK,5
BUY,Vodafone,STOCK,5
as you can see the ouput should be in alphabetical order (google is before vodafone) and also bonds should appear before stocks.
here is some setup code to help you:
public class main {
public static void main(String[] args){
String input = "Vodafone,STOCK,10|Google,STOCK,15|Microsoft,BOND,15:Vodafone,STOCK,15|Google,STOCK,10|Microsoft,BOND,15";
String output = matchBenchmark(input);
System.out.println(output);
}
public static String matchBenchmark(String input){
}
}
You should probably parse the input into a map:
Map keys should be <company>,<type>
Map values can be {<current-value>,<new-value>}
Then iterate over the map (you probably want to sort the keys) and print SELL or BUY according to the different between the current and new value.
Smth. like that:
public final class Market {
private final Pattern patternLine = Pattern.compile("(?<current>.+):(?<target>.+)");
private final Pattern patternData = Pattern.compile("(?<name>\\w+),(?<active>\\w+),(?<amount>[-]?\\d+)");
private final Pattern patternDataSplit = Pattern.compile("\\|");
public String matchBenchmark(String input) {
Matcher matcher = patternLine.matcher(input);
if (!matcher.matches())
throw new IllegalArgumentException();
Map<String, Data> current = getData(matcher.group("current"));
Map<String, Data> target = getData(matcher.group("target"));
return calc(current, target).stream()
.map(data -> data.getName() + ',' + data.getActive() + ',' + data.getAmount())
.collect(Collectors.joining("\n"));
}
private Map<String, Data> getData(String str) {
return Arrays.stream(patternDataSplit.split(str))
.map(patternData::matcher)
.filter(Matcher::matches)
.map(m -> new Data(m.group("name"), m.group("active"), Integer.parseInt(m.group("amount"))))
.collect(Collectors.toMap(Data::getName, Function.identity()));
}
private static final String BUY = "BUY";
private static final String SELL = "SELL";
private static Queue<Data> calc(Map<String, Data> current, Map<String, Data> target) {
Queue<Data> queue = new PriorityQueue<>(Data.SORT_BY_NAME_ACTIVE_ASC);
Set<String> names = new HashSet<>(current.keySet());
names.addAll(target.keySet());
for (String name : names) {
Data dataCurrent = current.get(name);
Data dataTarget = target.get(name);
if (dataCurrent == null) {
if (dataTarget.amount != 0)
queue.add(new Data(dataTarget.amount > 0 ? BUY : SELL, dataTarget.name, Math.abs(dataTarget.amount)));
} else if (dataTarget == null) {
if (dataCurrent.amount != 0)
queue.add(new Data(dataCurrent.amount > 0 ? SELL : BUY, dataCurrent.name, Math.abs(dataCurrent.amount)));
} else if (dataCurrent.amount != dataTarget.amount)
queue.add(new Data(dataTarget.amount > dataCurrent.amount ? BUY : SELL, dataCurrent.name,
Math.abs(dataTarget.amount - dataCurrent.amount)));
}
return queue;
}
public static final class Data {
public static final Comparator<Data> SORT_BY_NAME_ACTIVE_ASC = Comparator.comparing(Data::getActive).thenComparing(Data::getName);
private final String name;
private final String active;
private final int amount;
public Data(String name, String active, int amount) {
this.name = name;
this.active = active;
this.amount = amount;
}
public String getName() {
return name;
}
public String getActive() {
return active;
}
public int getAmount() {
return amount;
}
}
}
Related
When I run this code, it gives an error saying cannot involve get__() on the array type Book[].. In the main method, I have a book array with the information from a text file -- title, isbn, price, qty, forsale.
public static int searchByTitleOrISBN(Book[] b)
{
int i = 0;
// print a message "Enter the Title or ISBN of the book: "
System.out.println("Enter the Title or ISBN of the book: ");
String input = scan.next();
// use a while loop to search through the array books using a counter and as long as no match is found
while (i < b.length) {
// if there's a match for the title or a match for the isbn and the book quantity > 0 and the book is for sale
if ((b.getTitle().equals(title) || b.getISBN().equals(isbn)) & b.getQty() > 0 && b.isForSale()) {
Basically what you want is to search the entire list.If you want to keep up your present implementation, then the solution given by #Jens works.
But If you go by searching one by one it would be O(n) but if you leverage inbuilt HashMaps you can do it with O(1) using hashCode and equals and no need of looping through all the objects for each and every search.
the Book class which keeps the data of the book. hashCode and equals is implemented here.
public final class Book{
private final String title;
private final String isbn;
private double price;
private int quantity;
private boolean forSale;
public final Key key;
public Book(String title, String isbn, double price, int quantity,boolean forSale){
this.title = title;
this.isbn = isbn;
this.price = price;
this.quantity =quantity;
this.forSale = forSale;
this.key = makeKey(title,isbn);
}
private static Key makeKey(String title,String isbn) {
return new Key(title,isbn);
}
public Key getKey() {
return this.key;
}
public String getTitle(){
return this.title;
}
public String getISBN(){
return this.isbn;
}
#Override
public final String toString(){
String s = this.title +"; "+ this.isbn+ "; "+this.price+"; "+this.quantity;
return s;
}
public static final class Key{
private final String title;
private final String isbn;
private Key(String title,String isbn) {
this.title = title;
this.isbn = isbn;
}
private String getTitle() {
return this.title;
}
private String getISBN() {
return this.isbn;
}
//calculates the hash of the entry, if we don't override this it will
//use the hash of the reference. so we need to change it for comparision
#Override
public final int hashCode(){
return this.title.hashCode()+this.isbn.hashCode();
}
//if two components have same hash code, then we can use extra criterion
//to check if the two objects are same. in the book case the hash is
//unique.since we are using the title and the isbn;
#Override
public final boolean equals(Object obj){
if(this==obj){
return true;
}
if(obj!=null && this.getClass()==obj.getClass()){
Key tempObj = (Key)obj;
return (this.title == tempObj.getTitle()) && (this.isbn == tempObj.getISBN());
}
return false;
}
}
}
BookMap class which stores all the book objects in form of Map<Book.Key,Book>. This will help with the easy retrival of book data.
public final class BookMap{
private final Map<Book.Key,Book> map;
private final String name;
public BookMap(String name){
this.name = name;
this.map = new HashMap<>();
}
public final String getName(){
return this.name;
}
public final Map<Book.Key,Book> getMap(){
return Collections.unmodifiableMap(this.map);
}
public final void addBook(Book book){
this.map.put(book.getKey(),book);
}
public final Book getBook(Book book){
Book.Key tempKey = book.getKey();
return this.map.get(tempKey);
}
public final boolean findBook(Book book){
if(book != null) {
return this.map.containsKey(book.getKey());
}
return false;
}
#Override
public final String toString() {
String s ="Books list : \n";
for(Map.Entry<Book.Key,Book> b:this.map.entrySet()) {
s= s+b.getValue()+"\n";
}
return s;
}
}
Now a sample Main.js with static main method to retrieve the book list.
public class Main {
public static BookMap list = new BookSet("General list");
public static void main(String[] args) {
Book temp = new Book("Journey to the center of the earth","isbn-001-002-0455",9.99,15,false);
list.addBook(temp);
temp = new Book("The Time Machine","isbn-001-002-0456",9.99,15,false);
list.addBook(temp);
temp = new Book("The War of the Worlds","isbn-001-002-0457",8.99,15,false);
list.addBook(temp);
temp = new Book("Brave New World","isbn-001-002-0458",11.99,15,false);
list.addBook(temp);
temp = new Book("Ninteen Eighty-four","isbn-001-002-0459",19.99,15,false);
list.addBook(temp);
temp = new Book("Ray Bradbury","isbn-001-002-0460",14.99,15,false);
list.addBook(temp);
temp = new Book("I, Robot","isbn-001-002-0461",12.99,15,false);
list.addBook(temp);
temp = new Book("Foundation","isbn-001-002-0462",12.99,15,false);
list.addBook(temp);
temp = new Book("The Martial Chronicles","isbn-001-002-0463",3.99,15,false);
list.addBook(temp);
temp = new Book("Fahrenheit 451","isbn-001-002-0464",6.99,15,false);
list.addBook(temp);
//testing with the book already in the list;
temp = new Book("Fahrenheit 451","isbn-001-002-0464",0,0,false);
//prints book detail
System.out.println(list.getBook(temp));
//testing with the book already in the list;
temp = new Book("I am not in the list","isbn-001-002-0464",0,0,false);
//prints null as the book is not in the list
System.out.println(list.getBook(temp));
System.out.println(list);
}
}
The above is a rough idea, you can develop more on it, i have used final for classes in order to prevent subclassing, as it would become complex with inheritence to understand and debug.i like avoiding complexity as much as i can. If some common pattern is there, then i will try to use abstract classes.
You have to acces an element in your loop not the array itself:
while (i < b.length) {
// if there's a match for the title or a match for the isbn and the book quantity > 0 and the book is for sale
if ((b[i].getTitle().equals(title) || b[i].getISBN().equals(isbn)) & b[i].getQty() > 0 && b[i].isForSale()) {
This question already has answers here:
How to call a method in another class of the same package?
(8 answers)
Closed 2 years ago.
first I have three classes:
Data.java:
public class Data {
public static List<String> studentdataget(){
List<String> studentData = new ArrayList<String>();
// Format:
// Name ; Number ; Subject
studentData.add("Quee;810283;MathI");
studentData.add("Hor;812227;Math I");
studentData.add("Oper;810369;Math II");
studentData.add("Graf;811090;MathI");
studentData.add("Ingri;811911;MathI");
Student.java:
public class Student {
private static String name = "";
private static int number = 0;
private static String subject = "";
public Student(String name, int number, String subject) {
this.name = name;
this.number = number;
this.subject = subject;
}
public static String getnumber(String segs) {
return number;
}
public static int getnumber(String segs) {
return number;
}
public static String getName() {
return name;
}
public void setsubject(String subject) {
this.subject = subject;
}
public void setnumber(int number) {
this.number = number;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
String returnString = name + " (" + number + "), Subject: " + subject;
return returnString;
}
}
main.java:
public class main {
public static void main(String[] args) {
String path = "Name;number;subject";
String[] segs = path.split( Pattern.quote( ";" ) );
//System.out.println( (segs[2]));
HashMap<String, String> studentData = new HashMap<String, String>();
studentData.put(segs[1],segs[2]);
for (Map.Entry<String, String> pair: studentData.entrySet()) {
System.out.format("key: %s, value: %s\n", pair.getKey(), pair.getValue());
}
for(Map.Entry<String, String> pair: studentData.entrySet()) {
}
}
}
So the question is how can I put in my second for loop the list from my Data.class?
I want to display only the number and the subject is this possible ?
I have try so many ways and no one is getting me to the solution .. I hope someone can give me a solution
To access the studentData method from another class, you can use this notation Data.studentdataget(); since studentdataget() is static.
You just split() on ; in each entry of yout list to split them into [Quee, 810283, MathI]. Therefore you can use the last two indexes to get the desired data.
This assumes all the data in studentData remains uniform.
public static void main(String[] args) {
List<String> students = Data.studentdataget(); // access Data here
HashMap<String, String> classes = new HashMap<>();
// fill our map from the data found in Data.studentdataget
for (String student: students) {
String[] arr = student.split(";"); // split string into array on each ;
classes.put(arr[1], arr[2]); // fill map based on student data set
}
// print the map
for (Map.Entry<String, String> entry : classes.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
I would like to create a Json out of an array of strings which each look like:
"id.categoryvalue.subcatvalue.subsubcatvalue.score"
Result should look like this:
{
"user-id": "u42",
"categories": [
{
"category": "value",
"subcats": [
{
"subcat": "value",
"subsubcats": [
{
"subsubcat": "value",
"score": 47
}
]
}
]
}
]
}
I don't want to duplicate a value in the same category, what would be an effective way to solve it? Thanks!
With Gson you can generate the JSON using either the object model way or the streaming way. The first one requires the whole object to be built before generating the JSON either in a strongly typed manner (see below) or a weakly typed one (like what Darshan Mehta suggested -- he used a weak objects based on Java maps).
Object model approach
Decompose the given data into several data bag classes, construct the objects of these classes, an just invoke Gson:
public final class ObjectModelDemo {
private ObjectModelDemo() {
}
public static void main(final String... args) {
final String[] tokens = "id31.english.B1.Animals.11".split("\\.");
if ( tokens.length != 5 ) {
throw new IllegalArgumentException("Not 5 tokens in " + "id31.english.B1.Animals.11");
}
final String userId = tokens[0];
final String category = tokens[1];
final String subcategory = tokens[2];
final String subsubcategory = tokens[3];
final int score = parseInt(tokens[4]);
final User user = new User(
userId,
singletonList(new Category(
category,
singletonList(new Subcategory(
subcategory,
singletonList(new Subsubcategory(subsubcategory, score))
))
))
);
final Gson gson = new GsonBuilder().create();
out.println(gson.toJson(user));
}
private static final class User {
#SerializedName("user-id")
private final String userId;
#SerializedName("categories")
private final List<Category> categories;
private User(final String userId, final List<Category> categories) {
this.userId = userId;
this.categories = categories;
}
}
private static final class Category {
#SerializedName("category")
private final String category;
#SerializedName("subcats")
private final List<Subcategory> subcategories;
private Category(final String category, final List<Subcategory> subcategories) {
this.category = category;
this.subcategories = subcategories;
}
}
private static final class Subcategory {
#SerializedName("subcat")
private final String subcategory;
#SerializedName("subsubcats")
private final List<Subsubcategory> subsubcategories;
private Subcategory(final String subcategory, final List<Subsubcategory> subsubcategories) {
this.subcategory = subcategory;
this.subsubcategories = subsubcategories;
}
}
private static final class Subsubcategory {
#SerializedName("subsubcat")
private final String subsubcategory;
#SerializedName("score")
private final int score;
private Subsubcategory(final String subsubcategory, final int score) {
this.subsubcategory = subsubcategory;
this.score = score;
}
}
}
Such data bags are called DTOs (data-transfer objects) and are designed to map between Java objects and their respective JSON representation. This gives you very strong compile-time control support by the Java compiler. Disadvantage of this approach is that you must collect all the data before any JSON generation begins (usually this is very crucial for memory-sensitive applications). However, for your case, this can be much and much easier, and probably the most easy one.
The output:
{"user-id":"id31","categories":[{"category":"english","subcats":[{"subcat":"B1","subsubcats":[{"subsubcat":"Animals","score":11}]}]}]}
Streaming approach
An alternative approach based on intermediate writing a JSON to a destination. This approach is a data-pushing approach that is more complex, however it is more efficient from the memory consumption point of view (even more, you can easily generate infinite JSONs using this method, but I doubt you'll ever have such a situation :) ).
public static void main(final String... args)
throws IOException {
final String[] tokens = "id21.english.B2.Insects.24".split("\\.");
if ( tokens.length != 5 ) {
throw new IllegalArgumentException("Not 5 tokens in " + "id21.english.B2.Insects.24");
}
final String userId = tokens[0];
final String category = tokens[1];
final String subcategory = tokens[2];
final String subsubcategory = tokens[3];
final int score = parseInt(tokens[4]);
final JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(out));
writeUser(jsonWriter, userId, category, subcategory, subsubcategory, score);
jsonWriter.flush();
// do not invoke jsonWriter.close() -- let the caller decide what to do
}
private static void writeUser(final JsonWriter jsonWriter, final String userId, final String category, final String subcategory,
final String subsubcategory, final int score)
throws IOException {
jsonWriter.beginObject();
jsonWriter.name("user-id");
jsonWriter.value(userId);
jsonWriter.name("categories");
writeCategories(jsonWriter, category, subcategory, subsubcategory, score);
jsonWriter.endObject();
}
private static void writeCategories(final JsonWriter jsonWriter, final String category, final String subcategory, final String subsubcategory,
final int score)
throws IOException {
jsonWriter.beginArray();
jsonWriter.beginObject();
jsonWriter.name("category");
jsonWriter.value(category);
jsonWriter.name("subcats");
writeSubcategories(jsonWriter, subcategory, subsubcategory, score);
jsonWriter.endObject();
jsonWriter.endArray();
}
private static void writeSubcategories(final JsonWriter jsonWriter, final String subcategory, final String subsubcategory, final int score)
throws IOException {
jsonWriter.beginArray();
jsonWriter.beginObject();
jsonWriter.name("subcat");
jsonWriter.value(subcategory);
jsonWriter.name("subsubcats");
writeSubsubcategories(jsonWriter, subsubcategory, score);
jsonWriter.endObject();
jsonWriter.endArray();
}
private static void writeSubsubcategories(final JsonWriter jsonWriter, final String subsubcategory, final int score)
throws IOException {
jsonWriter.beginArray();
jsonWriter.beginObject();
jsonWriter.name("subsubcat");
jsonWriter.value(subsubcategory);
jsonWriter.name("score");
jsonWriter.value(score);
jsonWriter.endObject();
jsonWriter.endArray();
}
}
Pay attention on how data is written to the output stream: once you have enough known data, you can easily flush it to the output stream. Yep, this is a more hard-to-write approach, but this is an alternative.
The output:
{"user-id":"id21","categories":[{"category":"english","subcats":[{"subcat":"B2","subsubcats":[{"subsubcat":"Insects","score":24}]}]}]}
Assuming the format of input remains constant, you can do the following:
Tokenize the input string by splitting it with .
Declare/initialise the structures (e.g. Map and set appropriate values)
Convert resultant object to String using any JSON parser
Below example demonstrates it:
public static void main(String[] args) throws Exception{
Map<String, Object> result = convertToMap("id.categoryvalue.subcatvalue.subsubcatvalue.score");
System.out.println(new ObjectMapper().writeValueAsString(result));
}
public static Map<String, Object> convertToMap(String input){
Map<String, Object> result = new LinkedHashMap<>();
String[] tokens = input.split("\\.");
if(tokens.length < 5){
//Invalid string, return
throw new IllegalArgumentException("Insufficient tokens");
}
//Add user id
result.put("user-id", tokens[0]);
//Add category
Map<String, Object> category = new LinkedHashMap<>();
category.put("category", tokens[1]);
//Add sub category
Map<String, Object> subCategory = new LinkedHashMap<>();
subCategory.put("subcat", tokens[2]);
//Add nested category
Map<String, Object> nestedSubCategory = new LinkedHashMap<>();
nestedSubCategory.put("subsubcat", tokens[3]);
nestedSubCategory.put("score", Integer.parseInt(tokens[4]));
subCategory.put("subcats", Arrays.asList(new Map[] {nestedSubCategory}));
category.put("subcats", Arrays.asList(new Map[] {subCategory}));
result.put("categories", Arrays.asList(new Map[] {category}));
return result;
}
I am experimenting with a simple program that creates a bank account and has transactions tied to it. It works flawlessly when I am using primitive types, however I included a possibility of adding a String operation (such as ERROR when withdrawing), and now I am not sure how can I sort the list so that the String operations don't appear at all when printed out, if filtered, or appear at the bottom if sorted.
Full source code:
public static void main(String[] args) {
BankAccount bankAccount = new BankAccount();
bankAccount.addTransaction(2, TransactionType.DEPOSIT);
bankAccount.addTransaction(100.66, TransactionType.DEPOSIT);
bankAccount.addTransaction(2, TransactionType.WITHDRAW);
bankAccount.addTransaction("ERROR", TransactionType.WITHDRAW);
List<Transaction> transactions = bankAccount.getTransactions();
List<Transaction> collect = transactions.stream()
//Error appears over here, probably due to wrong syntax of the two next lines.
.sorted(Comparator.comparing((Transaction tr) -> tr.getAmount()).reversed())
.filter(tr -> tr.getAmount() > 0)
.collect(toList());
collect.forEach(tr -> System.out.println(tr));
}
private static class BankAccount {
private List<Transaction> transactions = new ArrayList<>();
public <T> void addTransaction(T amount, TransactionType transactionType) {
Transaction transaction = new Transaction(amount, transactionType);
transactions.add(transaction);
//return 0;
}
public List<Transaction> getTransactions() {
return Collections.unmodifiableList(transactions);
}
#Override
public String toString() {
return "BankAccount{" +
"transactions=" + transactions +
'}';
}
}
private static class Transaction<T> {
private final T amount;
private final TransactionType transactionType;
private final Date dateCreated;
public Transaction(T amount, TransactionType transactionType) {
this.amount = amount;
this.transactionType = transactionType;
this.dateCreated = new Date();
}
public T getAmount() {
return amount;
}
public TransactionType getTransactionType() {
return transactionType;
}
public Date getDateCreated() {
return dateCreated;
}
#Override
public String toString() {
return "Transaction{" +
"amount=" + amount +
", transactionType=" + transactionType +
", dateCreated=" + dateCreated +
'}';
}
}
private static enum TransactionType {
DEPOSIT, WITHDRAW;
}
}
Your issue is you are comparing apples to oranges when you mix Transaction<Double> with Transaction<String>. Your BankAccount can only hold one type of Transaction. They are either all Transaction<Double> or Transaction<String>.
Right now because you do not have your BankAccount class parameterized it is treating it like Transaction<Object>.
The solution is to properly parameterize the BankAccount and code accordingly. Here is a version coded up using BankAccount<String>.
NOTE: The example is relying on String comparison of numbers which is not a sound strategy. I moved the filter() call up to remove the "ERROR" transactions first. Then you will want to consider parsing back to numbers in the function you pass to comparing().
public static void main(String[] args) {
BankAccount<String> bankAccount = new BankAccount<>();
bankAccount.addTransaction(Double.toString(2.00), TransactionType.DEPOSIT);
bankAccount.addTransaction(Double.toString(100.66), TransactionType.DEPOSIT);
bankAccount.addTransaction(Double.toString(2.00), TransactionType.WITHDRAW);
bankAccount.addTransaction("ERROR", TransactionType.WITHDRAW);
List<Transaction<String>> transactions = bankAccount.getTransactions();
List<Transaction<String>> collect = transactions.stream()
.filter(tr -> !tr.getAmount().equals("ERROR"))
.sorted(Comparator.<Transaction<String>, String> comparing(transaction -> transaction.getAmount()).reversed())
.collect(Collectors.toList());
collect.forEach(tr -> System.out.println(tr.getAmount() + " " + tr.getType().name()));
}
public static class BankAccount<T> {
private List<Transaction<T>> transactions = new ArrayList<>();
public void addTransaction(T amount, TransactionType transactionType) {
Transaction<T> transaction = new Transaction <>(amount, transactionType);
transactions.add(transaction);
}
public List<Transaction<T>> getTransactions() {
return Collections.unmodifiableList(transactions);
}
}
public static class Transaction<T> {
private final T amount;
private final TransactionType transactionType;
private final Date dateCreated;
public Transaction(T amount, TransactionType transactionType) {
this.amount = amount;
this.transactionType = transactionType;
this.dateCreated = new Date();
}
public T getAmount() {
return amount;
}
public TransactionType getType(){
return transactionType;
}
public Date getDateCreated(){
return dateCreated;
}
}
public enum TransactionType {
DEPOSIT, WITHDRAW;
}
If you want to compare (sort) objects with different type why don't you for example write own Comparator for it?
Example:
List<Transaction> collect = transactions.stream()
.sorted((t1, t2) -> {
if (t1.getAmount() instanceof String && t2.getAmount() instanceof String) {
return String.class.cast(t1.getAmount()).compareTo(String.class.cast(t2.getAmount()));
} else if (t1.getAmount() instanceof String) {
return 1;
} else if (t2.getAmount() instanceof String) {
return -1;
} else {
return new BigDecimal(t1.getAmount().toString()).compareTo(new BigDecimal(t2.getAmount().toString())); //ugly hack
}
})
.filter(tr -> tr.getAmount() instanceof Number && Number.class.cast(tr.getAmount()).doubleValue() > 0) //next ugly hack
.collect(Collectors.toList());
collect.forEach(System.out::println);
I am using a custom class object as the key for a HashMap. In this class definition, I have overridden the equals() and hashCode() methods.
public class TimeTableDataModel {
Map <Course, List <Timings>> tm;
TimeTableDataModel() {
tm = new HashMap<>();
}
void addCourseItem(Course course) {
tm.put(course, new ArrayList<Timings>());
}
void addNewTimeTableItem(Course course, Timings newTiming) {
List <Timings> t;
if(!tm.containsKey(course)) {
addCourseItem(course);
}
t = tm.get(course);
t.add(newTiming);
tm.put(course, t);
}
public static final class Course {
private final String courseCode;
private final String courseName;
private final String section;
private final String group;
Course(String code, String courseName, String section, String group) {
this.courseCode = code;
this.courseName = courseName;
this.section = section;
this.group = group;
}
public String getCourseCode() { return courseCode; }
public String getCourseName() { return courseName; }
public String getSection() { return section; }
public String getGroup() { return group; }
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Course)) {
return false;
}
Course otherObj = (Course) obj;
return Objects.equals(courseCode,otherObj.courseCode)
&& Objects.equals(courseName, otherObj.courseName)
&& Objects.equals(section, otherObj.section)
&& Objects.equals(group, otherObj.group);
}
#Override
public int hashCode() {
return Objects.hash(courseCode, courseName, section, group);
}
}
public static class Timings {
String time;
String day;
String room;
Timings(String time, String day) {
setTime(time);
setDay(day);
}
public String getTime() { return time; }
public String getday() { return day; }
public void setTime(String time) { this.time = time; }
public void setDay(String day){this.day = day;}
}
}
In above code I have created Course class to be used as the key for the HashMap and using a List<Timings> for values. What I intend is to get a List of timings when a Course is passed to hm.get(course). So far I can get a keyset then sequentially get values for each course.
for(Course c : timetable.tm.keySet()) {
System.out.println(c.getCourseCode() + " " + c.getCourseName());
for(Timings t : timetable.tm.get(c)) {
System.out.println(t.time + " " +t.room + " "+ t.day);
}
};
Here's the code that populates the HashMap
static TimeTableDataModel timetable = new TimeTableDataModel();
Course course = new Course(courseCode,null,section,group);
Timings dt = new Timings(time, getDayOfWeek(i));
dt.room = roomNo;
timetable.addNewTimeTableItem(course, dt);
So to get the timings for a particular course I have to traverse the whole HashMap until the desired course Key is found. What I want is a way to distinguish between each course object contained in the HashMap Key, so I can get Timings for any random course without traversing the whole KeySet.
Thanks in advance. Please ask if somethings is unclear in code
Problem what I see here is
if(!tm.containsKey(course)){
addCourseItem(course);
}
and
if (this == obj) {
return true;
}
because you are comparing the object. Since both are same class objects equals will always return true and map concludes it as duplicate key.