I have a question about an assignment that i am being required to complete.
Write a menu driven program that either accepts words and their meanings, or displays the list of words in lexicographical order (i.e. as in a dictionary). When an entry is to be added to the dictionary you must first enter the word as one string, and then enter the meaning as separate string. A word may have more than one meaning, and may be entered at separate times. When this occurs, place each successive meaning on a separate line. This new meaning must be preceded by a dash. For example, if you enter the following words and with their meanings in the following order: Library, School, Cup, and School, then your output should be a display as shown in the Figure 1.
Use the concept of linked list to carryout this exercise. You will need at minimum the following classes:
• A WordMeaning class that hold the name of a word and its meaning.
• A WordMeaningNode class that creates the node of information and its link field.
• A WordList class that creates and maintain a linked list of words and their meanings.
• A Dictionary class that test your classes.
The question concerns the second bullet. I am not sure about how to go about creating a constructor for WordMeaningNode. This is what I have so far:
import java.lang.*;
import java.util.*;
public class WordMeaningNode
{
String information;
WordMeaningNode locale;
public WordMeaningNode(WordMeaning data)
//WordMeaning is a class that takes two strings(Word and definition) and stores it.
//Entry is a method that returns the strings stored in WordMeaning.
{
information = data.Entry();
locale = null;
}
public String getMeaning()
{
return information;
}
public WordMeaningNode getNext()
{
return locale.getNext();
}
}
A couple things:
First, I think you would be better passing in the String that results from data.entry(). That was you can create your constructors in the following manner:
public WordMeaningNode(String entry){
int index = entry.indexOf(',') + 1; //Assuming your String is comma delimited.
information = entry.substring(0, index);
String next = entry.substring(index);
if(next.isEmpty()){
locale = null;
} else {
locale = new WordMeaningNode(next);
}
}
Second, is your getNext() method working correctly? It seems like that would always give a null pointer exception.
Good luck!
Related
Object[] x = new Object[] {"Skye", "Eyks", 123}
{
#Override
public String toString()
{
return this[0] + " " + this[1] + " (" + this[3] + ")";
}
};
So that x.toString() would return "Skye Eyks (123)".
NetBeans says it expects a semi-colon and that it's an Illegal start of expression.
Why I want to use an anonymous array class is to display the data in a combo-box and get all the other data in my array once the user submits the form.
No, this is impossible.
Your code paste strongly suggests an alternate solution:
Java is a statically and nominally typed object oriented language. Java is very very bad at dealing with data stored in a heterogenerous, untyped, and unnamed 'grabbag of unknown mystery' - which is what Object[] is.
This is presumably what you're looking for:
public class Word {
final String word;
final int score;
public String getWord() {
return word;
}
public String getReverse() {
// ...
}
public int getScore() {
return score;
}
#Override public String toString() {
return word + " " + getReverse() + " (" + score + ")";
}
}
Now, it's got structure (the compiler now knows, and your editor can now help you out): a Word has properties like getWord() and getReverse(); getReverse() is far more informative than [1]. You now have a place to add documentation if you want (how do you intend to 'document' new Object[]?), and you have room for flexibility (for example, getReverse() could be calculated on the fly instead of passed in at construction).
You can now write methods that take a Word. This:
public void printWord(Word word) {}
is almost self evident. Compare to this:
/**
* This function requires that you pass a 3-sized object array, with:
* The first argument must be a string - this is the word to print.
* The second argument must be that string, reversed. It will be printed in light grey for a mirror effect.
* The third argument must be a boxed integer, this will be printed in the lower right corner as page number
*/
public void printWord(Object[] o) {}
That's a ton of documentation, and this is considerably worse: This documentation is unstructured - whereas with an actual class, the names of methods can carry most of this meaning and lets you document each fragment independently. You can also farm out any checks and other code to the right place, instead of ending up in a scenario where the code to check if the input array is proper needs to be called in many places, and you need to go out of your way to document, for everything, what happens if you pass invalid input (vs. having to do that only once, in Word's constructors).
If you end up with an Object[] due to external forces, such as, say, the arguments passed along to your main function, then the general aim is to convert that to a proper object once, and as soon as possible, so that your java code remains as uninfected by this heterogenous, untyped and unnamed mysterymeat as possible.
NB: Yes, that means you need to make a ton of classes, for everything you can think of, so you end up with clean code. Lombok's #Value can help with this, as can java15's records.
How can I check if my Input String is in my ArrayList?
I did it like this. But it always shows "not equal". Althoug I insert 1 for example:
public class Main {
public static void main(String[] args) {
String Input = JOptionPane.showInputDialog("Input:");
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
if (Input.equals(list)) {
JOptionPane.showMessageDialog(null, "equals");
} else {
JOptionPane.showMessageDialog(null, "not equal");
}
}
}
If you want to check does List<T> contains T item you should use yourList.contains(T item) in your code, you are using item.equals(object) which is completely different. In short what equals() does is it checks do both objects are stored in the same memory address. Although for some default classes this method is overwritten and works a different way, String class is a good example of that.
Explanation
You wrote
if (Input.equals(list)) { ... }
with Input being a String and list an ArrayList. But, the String#equals (documentation) method compares if two Strings have the same characters (like "hello".equals("hello")), not if the argument list contains the element you called the method on. To quote from its documentation:
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
Solution
What you actually want to use is List#contains (documentation):
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that Objects.equals(o, e).
So the code might look like:
if (list.contains(Input)) { ... }
Naming convention
Please note naming conventions. Variable names should always be in camelCase, so input instead of Input. Same for method names.
Only class names are written in PascalCase. And constants (static final) are written in uppercase SNAKE_CASE.
Like the title says, I have an ArrayList in java with Objects. The Objects are basically room types in a hotel. they all have a typename, amount of beds etc. Now my problem is, I need to find two objects with the same value for the typename field. I got as far as looping through the list with a for loop but cant figure out how to continue. Here's my code:
import java.util.ArrayList;
public class KamerType {
private String typeNaam;
private int aantalBedden;
private double prijsPerNacht;
public KamerType(String tN, int aB, double pPN){
typeNaam = tN;
aantalBedden = aB;
prijsPerNacht = pPN;
}
public String toString(){
String s = "De kamer van type " + typeNaam + " heeft " + aantalBedden + " bedden en kost " + prijsPerNacht + " euro.";
return s;
}
public static void main(String a[]){
ArrayList<KamerType> kamertypes = new ArrayList<KamerType>();
KamerType k1 = new KamerType("Standaard", 2, 60.0);
kamertypes.add(k1);
KamerType k2 = new KamerType("DeLuxe", 2, 85.0);
kamertypes.add(k2);
KamerType k3 = new KamerType("DeLuxe", 4, 125.0);
kamertypes.add(k3);
KamerType k4 = new KamerType("Hiker", 2, 35.0);
kamertypes.add(k4);
System.out.println("Dit zijn de kamertypen:");
for(KamerType KT : kamertypes){
System.out.println(KT.toString());
}
System.out.println("\nTesten op zelfde typenaam:");
for(KamerType KT : kamertypes){
/*if(kamertypes.get(1).typeNaam == KT.typeNaam){
???
}*/
}
} // end of main
}// end of class
Any help is appreciated :)
Edit: two working answers have been given by npinti and Djorde Ivanovic, npinti gave a more guideline-ish answer. Thanks alot guys :)
Since this sounds like home work, I'll try and provide some basic guidelines as opposed to solutions.
The most basic (albeit less efficient) way would be to do a nest loop and compare the rooms:
(I assume that if an object has all 3 fields which are the same, then, I am referencing the same object. Thus, this part: AND (r1.aantalBedden != r2.aantalBedden)) AND (r1.prijsPerNacht != r2.prijsPerNacht) would help me avoid saying that I have a duplicate (when comparing the same object).
for each KamerType r1 in kamertypes
for each KamerType r2 in kamertypes
if(((r1.typeNaam.equals(r2.typeNaam)) AND (r1.aantalBedden != r2.aantalBedden)) AND (r1.prijsPerNacht != r2.prijsPerNacht))
print("We have duplicates");
An alternative, more standard (if you will) way of doing it would be to:
Make your KamerType class override the equals method, and change it such that two KamerType objects are the same if they have the same typeNaam field.
Use a data structure such as a Set (which does not allow duplicates) and place your KamerType objects in it. This will internally invoke the equals method and if it yields true, then, it will nod add the room to the set, thus allowing you to end up with a list of KamerType objects which are unique.
As a minor note, I also noticed this in your code: if(kamertypes.get(1).typeNaam == KT.typeNaam). In Java, string comparison is done through the equals method, so that should become if(kamertypes.get(1).typeNaam.equals(KT.typeNaam)).
EDIT: As per your comment, the second approach would allow you to solve the problem by going once through the list. There would also be a third approach to solve this problem however I think that it is the worst part of both solutions I provided above (slightly complicated to implement, and the execution might take longer).
Make your KamerType class implement the Comparable interface. This will force you to implement the compareTo()* method. In your implementation, you simply (in this case at least) compare the typeNaam. Then sort the list.
Once that you will have your sorted list, start from the second element of your list and compare it with the previous one. Since your list is sorted by typeNaam, any two objects which have the same typeNaam field will be exactly next to each other in your list, so you would be able to find duplicates without having a O^2 time complexity.
This will allow you to call Collections.sort() and make it sort your collection in a way you want it.
to compare strings, use 'equals' function instead of '=='
like this
if(kamertypes.get(1).typeNaam.equals(KT.typeNaam))
First create a getter method for your field:
public String getTypeNaam() {
return typeNaam;
}
Then you can compare the two values:
if(kt1.getTypeNaam().equals(kt2.getTypeNaam)) {
// Name of kt1 and kt2 is identical
}
If you want to compare each object which each other, use nested loops:
for(KamerType kt1 : kamertypes){
for(KamerType kt2 : kamertypes) {
if(kt1.getTypeNaam().equals(kt2.getTypeNaam)) {
// Name of kt1 and kt2 is identical
}
}
}
Be aware that this also finds two identical objects because they of course have the same name. You can exclude those by adding the condition kt1 != k2 to your if.
Here is what you need. First add getter for your private fields. I used loops with i and j to avoid duplicating.
for(int j = 0;j<kamertypes.size();j++){
for(int i = j+1;i<kamertypes.size();i++){
if(kamertypes.get(j).getTypeNaam().equals(kamertypes.get(i).getTypeNaam()) && i!=j){
System.out.println(kamertypes.get(j) + " and " +kamertypes.get(i));
}
}
}
I have this problem where there are several parts in my code where I check if these certain conditions are met so that I can understand if what I am checking is of one type or the other. this ends up becoming large if else trees because I am making lots of checks, the same checks in each method, and there are several different types the thing I am checking can be. This I know can be solved using objects!
Specifically, the things I am checking are 4 string values from a file. based on these string values, the 4 strings together can make one of 3 types. Rather than making these same checks every time I need to get the type the 4 strings make up, I am wondering if I can create a general object given these 4 strings and then determine if that object is an instanceof either specific class 1, 2, or 3. Then I would be able to cast that general object to the specific object.
Say I name the general object that the 4 strings create called Sign. I would take those 4 strings and create a new Sign object:
Sign unkownType = new Sign(string1, string2, string3, string4);
I need to check which specific type of sign this sign is.
EDIT:
for more detail, the Signs I am checking are not symbols like "+" or "-", they are signs with text like you would see on the road. there are 4 lines on each sign and they need to be checked to see if each line evaluates to match a specific type of sign.
The first line of SignType1 will be different of the first line of SignType2, and I want to take those 4 lines (Strings) and pass it onto an object and use that object throughout my code to get the values from it rather than making the same checks in each method.
If you want me to show some code, I can, but it won't make much sense.
What you seem to asking for is a factory pattern
public interface ISign {
public void operation1();
public void operation2();
}
and a Factory class to generate classes based on input
public class SignGenerator {
public static ISign getSignObject(String str1,String str2, String str3, String str4) {
if(str1.equals("blah blah"))
return new FirstType();
if(str1.equals("blah blah2") && str2.equals("lorem ipsum"))
return new SecondType();
return new ThirdType();
}
}
public class FirstType implements ISign {
}
public class SecondType implements ISign {
}
public class ThirdType implements ISign {
}
Implement all Type specific logic in these classes so you can call them without checking with tons of if..else clauses first
From what I gathered from your statement.
Say: create the method that returns a certain object provided the given string is equal to whateva value you specify
//provided the objects to be returned are subtypes of Sign
public Sign getInstance(String first, String second, String third, String fourth)
{
if(first==null || second==null || third==null || fourth===null )
return null;
if(compare1.equals(first))
return new SignType1();
else
if(compare2.equals(second))
return new SignType2();
else
if(compare3.equals(third))
return new SignType3();
else
if(compare4.equals(fourth))
return new SignType4();
}
Above code checks and returns thee appropriet instance corresponding to the string passed
Hope that's what was your concern
I have text file. In that i want to remove duplicate words.My text file contains words like
அந்தப்
சத்தம்
அந்த
இந்தத்
பாப்பா
இந்த
கனவுத்
அந்த
கனவு
I remove duplicate words. But the words which has ending 'ப்' , 'த்' are consider as seperate words and not able to remove as duplicate word. If i remove 'ப்' , 'த்' it remove from some other words like பாப்பா, சத்தம். Please suggest any ideas to solve this problem using java.Thanks in advance.
I think I would use a Set with a custom comperator (such as a TreeSet). That way you can define equals any way you like.
I don't understand the given language (google translate's guess is Tamil), but from your question I read, that there are special rules for 'equality' for words written in that language - like words can be equal even if they're written differently (e.g. with different endings).
So you may want to wrap the strings containing words of that language in special object where you can define a custom 'equals' method, like this:
public class TamilWord {
String writtenWord = null;
public TamilWord(String writtenWord) {
this.writtenWord = writtenWord;
}
public String getWrittenWord() {
return writtenWord;
}
#Overwrite
public boolean equals(Object other) {
// Define your custom rules here, so that two words that
// are written differently may be considered as equal
}
}
Then you can create TamilWord objects for all parsed Strings and drop them into
a Set. So if we have the word abcd and abcD which are different in writing but according to rules considered equal, only one of those will be added to the set.
Use a scanner to scan in each line as a string into a set then write the strings in the set to a file.
First you should explain us how you parse your file, as it seems that your tokenization is not working appropriately. Then, to my mind, the obvious suggestion to a query for unduplication is to use a Set (and even a TreeSet) which should ensure uniqueness of your elements according to given Set contains rules.
My way to solve this:
Read word by word and put it to java.util.Set<TheWord>. Finally, you will have the Set with no duplicates. You also should define TheWord class:
class TheWord {
String word;
public TheWord() {}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public boolean equals(TheWord o) {
// put here your specific way to compare words
// taking into account your language rules and considerations
}
}