I've given an assigment and its the last day of itself. I did most of it but on the last question I have a problem with creating a compareTo() function.
Here is what it does want from us ;
compareTo
public int compareTo(java.lang.Object other)
Specified by:
compareTo in interface java.lang.Comparable
Here is what I did
public int compareTo(Object obj)
{
Document tmp = (Document)obj;
if(this.text < tmp.text)
{
/* instance lt received */
return -1;
}
else if(this.text > tmp.text)
{
/* instance gt received */
return 1;
}
/* instance == received */
return 0;
}
Here is my whole Document.java file
class Document
{
private String text;
/**
* Default constructor; Initialize amount to zero.
*/
public Document()
{
text = "";
}
/**
* Default constructor; Initialize text to input value
* #param text New text value
*/
public Document(String text)
{
this.text = text;
}
/**
* Returns as a string the contents of the Document.
*/
public String toString()
{
return text;
}
and Here is the test file of itself.
import java.util.Arrays;
public class Homework2 extends Document {
/** ======================
* ContainsKeyword
* Returns true if the Document
* object passed in contains keyword as a substring
* of its text property.
* ======================
*/
public static boolean ContainsKeyword(Document docObject, String keyword)
{
if (docObject.toString().indexOf(keyword,0) >= 0)
return true;
return false;
}
public static void main(String[] args){
Email email1= new Email("Programming in Java",
"Larry", "Curly", "Programming");
Email email2 = new Email("Running marathons",
"Speedy", "Gonzales", "races");
System.out.println(email1);
File file1 = new File("Some Java file", "file.txt");
File file2 = new File(
"Boluspor wins against Besiktas. Muahahahaha",
"bolutas.txt");
Document doc = new Document (
"ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?");
System.out.println("\n"+file1);
System.out.println("\nWhich contains Java?");
if (ContainsKeyword(email1,"Java")) System.out.println(" Email1");
if (ContainsKeyword(email2,"Java")) System.out.println(" Email2");
if (ContainsKeyword(file1,"Java")) System.out.println(" File1");
if (ContainsKeyword(file2,"Java")) System.out.println(" File2");
Document [] da = new Document [5];
da[0] = email1;
da[1] = email2;
da[2] = file1;
da[3] = file2;
da[4] = doc;
Arrays.sort(da);
System.out.println("\nAfter sort:");
for(Document d : da){
System.out.println(d);
}
}
}
What I wanted to ask is, I cannot compare the objects from my Email.java and File.java , I can do anything else but the last part which starts with Document [] da... That part gives an error. What am I doing wrong here?
The error is ;
Exception in thread "main" java.lang.ClassCastException: Email cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.sort(Arrays.java:1079)
at Homework2.main(Homework2.java:53)
UPLOAD ** Here is my Email and File Class..
/**
* First define class for Email, derive from Document
*/
class Email extends Document
{
private String sender;
private String recipient;
private String title;
private String body;
/**
* Constructors
*/
public Email()
{
super();
sender = "";
recipient = "";
title = "";
body = "";
}
public Email(String body, String sender, String recipient, String title)
{
this.sender = sender;
this.recipient = recipient;
this.title = title;
this.body = body;
}
// ======================
// Various accessor and mutator methods
// ======================
public String getSender()
{
return sender;
}
public void setSender(String sender)
{
this.sender = sender;
}
public String getRecipient()
{
return recipient;
}
public void setRecipient(String recipient)
{
this.recipient = recipient;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getBody(){
return body;
}
public void getBody(String body){
this.body = body;
}
/**
* Returns as a string the contents of the text fields concatenated
* together. Uses super.toString to get the parent's text.
*/
public String toString()
{
return "Sender:" + sender + ",Recipient:" + recipient + ",Title:" + title + ",Body:" + body + " " +
super.toString();
}
} // Email
and File ;
/**
* Next define class for File, derive from Document
* For brevity, short one-line methods are defined here in the
* header.
*/
class File extends Document
{
private String pathname;
/**
* Constructors.
*/
public File()
{
super();
pathname = "";
}
public File(String body, String pathname)
{
super(body);
this.pathname = pathname;
}
// ======================
// Various accessor and mutator methods
// ======================
public void setPathname(String s)
{
pathname = s;
}
public String getPathname()
{
return pathname;
}
/**
* Returns as a string the contents of the text fields concatenated
* together. Uses super.toString to get the parent's text.
*/
public String toString()
{
return "Pathname " + pathname + " Body " + super.toString();
}
} // File
Where did you put the compareTo method? If you're trying to sort an array of Documents, you need to have Document implement Comparable (or pass in a Comparator):
public class Document implements Comparable<Document> {
Or, if for some bizarre reason you're not allowed to use generics:
public class Document implements Comparable {
Then put compareTo within Document.
The exact reason it is failing is because you are trying to call Arrays.sort on a class that does not implement comparable
Implementing Comparable allows
calling Collections.sort and Collections.binarySearch
calling Arrays.sort and Arrays.binarySearch
using objects as keys in a TreeMap
using objects as elements in a TreeSet
Email did not implement the Comparable interface
use
public class Email implements Comparable<Email>
read this to do yourself a favor http://www.javapractices.com/topic/TopicAction.do?Id=10
The other note is you said you want to compare
Email.java and File.java
You will need a custom function for that based on the logic.
compareTo is used to compare two instances of the same type. It also means that the function lives in the Email class
Email myEmail = new Email();
Email hisEmail = new Email();
myEmail.compareTo(hisEmail);
What you are doing wrong is in the error message.
You can only sort objects for classes which implement Comparable. Your class does not.
As you are sorting a number of different types you may want to provide a custom Comparator instead, or make Document implement Comparable.
try this:
Here is my whole Document.java file
class Document implements Comparable { //this line is your solution.
private String text;
/**
* Default constructor; Initialize amount to zero.
*/
public Document()
{
text = "";
}
/**
* Default constructor; Initialize text to input value
* #param text New text value
*/
....}
Related
I'm trying to make a new object type which is intended to act like a subclass of String. I'm aware a class cannot extend String. I'm making application that has requirements such as a Contact's first name cannot be longer than 10 characters, and cannot be null, the last name cannot be more than 15 characters.
I started off making the class like so:
package Models;
/**
* #author Charles Hilton
*
*/
public class LimitedString {
private String value;
private static final String descriptor;
private static final Integer minimumLength;
private static final Integer maximumLength;
private static final boolean nullable;
public LimitedString(String value, String descriptor, Integer maximumLength, Integer minimumLength, boolean isNullable) throws Exception {
if (minimumLength < 0) {
throw new IllegalArgumentException("Minimum length cannot be less than 0");
}
if (minimumLength > maximumLength) {
throw new IllegalArgumentException("Minimum length cannot be greater than maximum length");
}
this.minimumLength = minimumLength;
this.maximumLength = maximumLength;
this.nullable = isNullable;
this.descriptor = descriptor; // i.e. descriptor = "Contact First Name"
this.setValue(value);
}
LimitedString(String descriptor, Integer maximumLength, Integer minimumLength, boolean isNullable) {
if (minimumLength < 0) {
throw new IllegalArgumentException("Minimum length cannot be less than 0");
}
if (minimumLength > maximumLength) {
throw new IllegalArgumentException("Minimum length cannot be greater than maximum length");
}
this.minimumLength = minimumLength;
this.maximumLength = maximumLength;
this.nullable = isNullable;
this.descriptor = descriptor; // i.e. descriptor = "Contact First Name"
this.setValue(value);
}
public String ToString() {
return this.value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
if (value == null && !nullable) throw new IllegalArgumentException("The value cannot be null.");
if (value.length() < minimumLength || value.length() > maximumLength) {
throw new IllegalArgumentException(String.format("#s must be between %s character(s) and %s characters long.", descriptor, minimumLength, maximumLength));
}
this.value = value;
}
public static String getDescriptor() {
return descriptor;
}
public static Integer getMinimumlength() {
return minimumLength;
}
public static Integer getMaximumlength() {
return maximumLength;
}
public static boolean isNullable() {
return nullable;
}
}
then using it in a Contact class like so:
/**
*
*/
package Models;
/**
* #author Charles Hilton
*
*/
public class Contact {
private LimitedString firstName = new LimitedString("First Name", 10, 1, false);
private LimitedString lastName = new LimitedString("Last Name", 15, 1, false);
private Contact() {};
public Contact(String lastName, String firstName) {
this.setLastName(lastName);
this.setFirstName(firstName);
}
public String getFirstName() {
return firstName.getValue();
}
public void setFirstName(String firstName) {
this.firstName.setValue(firstName);
}
public String getLastName() {
return lastName.getValue();
}
public void setLastName(String lastName) {
this.lastName.setValue(lastName);
}
}
I'm worried that it could be optimized better. For starters, in LimitedString. I made several fields static and final with the intention of trying to minimize memory usage as more contacts are added to a collection, which I apparently can't do the way I have it setup right now.
CharSequence
To directly answer your question, I suggest writing a class that implements the CharSequence interface. String, StringBuilder, and some other classes implement that interface.
If you want to be able to add more text to an existing object of your class, your class should also implement Appendable.
I imagine your class would contain a String. If appendable, perhaps a StringBuilder.
I don’t see the need for your descriptor field.
Rather than carry a nullable field, consider writing two classes. One is a subclass of the other, one tolerating a null, the other not.
Jakarta Bean Validation
A better solution to needs like null-checks, and like limiting the size of a field, is Jakarta Bean Validation. See specification page; Version 3 is current. See project page (a bit outdated).
Some validators are provided. And you can write your own validators.
You can invoke validators in your code. And the validators can be invoked by a user-interface built in JavaFX or built in Vaadin Flow.
I believe that the provided validators NotNull and Size would accomplish your goals. But NotBlank is better than NotNull as it also checks that the non-null text contains at least one non-whitespace character.
#NotBlank
#Size( min=1 , max=10 )
private String firstName ;
I'm reasonably confident in my first generics container, but stuck on how to word the casting on the client side. This is what was working before I got involved in learning <T> stuff:
CommonNounContainer typeContainer = new Json().fromJson(CommonNounContainer.class, result);
I was looking at having to create a different container for each class, and that doesn't seem like good design. Below is my updated, non-working attempt to read in my new generics container:
JSONContainer<CommonNoun> typeContainer = new Json().fromJson(JSONContainer.class, result);
My IDE doesn't care for this phrasing, noting:
Type safety: The expression of type JSONContainer needs unchecked
conversion to conform to JSONContainer
When executed, my err log reads:
result = {"myObject":{"cid":{"oid":129},"name":"technology","form":1},"children":[]}
com.badlogic.gdx.utils.SerializationException: Field not found: cid (java.lang.Object)
Serialization trace:
{}.myObject.cid
myObject (semanticWeb.rep.concept.JSONContainer)
at com.badlogic.gdx.utils.Json.readFields(Json.java:854)
at com.badlogic.gdx.utils.Json.readValue(Json.java:1011)
at com.badlogic.gdx.utils.Json.readFields(Json.java:863)
at com.badlogic.gdx.utils.Json.readValue(Json.java:1011)
at com.badlogic.gdx.utils.Json.fromJson(Json.java:789)
at com.b2tclient.net.Communicator$2.handleHttpResponse(Communicator.java:95)
at com.badlogic.gdx.net.NetJavaImpl$2.run(NetJavaImpl.java:224)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:830)
I'm sure there's some way I'm supposed to include a reference to the CommonNoun type to the right of the equals sign, but I haven't been able to figure it out. How do I do it? There's lots of applicable posts concerning generics, casting, JSON, and stripping away of class information. One of them I tried to follow that wasn't about the casting above regarded adding the T class as a private variable within the container during construction:
How do I get a class instance of generic type T?
but I ran into similar syntax issues trying to refer to the class correctly, just in a different spot along the process. I have my doubts, too, that I can read this class variable from the JSON file before telling JSON how to classify the information in the file.
Javadoc for the fromJson(Class<T>, String) method:
Type Parameters:
<T>
Parameters:
type May be null if the type is unknown.
json
Returns:
May be null.
I may already have a viable answer submitted by deduper, but, as requested, here are the CommonNounContainer and JSONContainer classes:
import java.util.ArrayList;
public class CommonNounContainer {
private CommonNoun myCommonNoun;
private ArrayList<CommonNounContainer> children;
public CommonNounContainer(CommonNoun concept) {
myCommonNoun = concept;
children = new ArrayList<CommonNounContainer>();
}
//Creates an empty shell. This would be for categories you want to group by, but not display/select in the select box.
public CommonNounContainer() {
children = new ArrayList<CommonNounContainer>();
}
public void addChildren(ArrayList<CommonNounContainer> newChildren) {
children.addAll(newChildren);
}
public void addChild(CommonNoun concept) {
children.add(new CommonNounContainer(concept));
}
public ArrayList<CommonNounContainer> getChildren() {
return children;
}
public CommonNoun getValue() {
return myCommonNoun;
}
public boolean hasChildren() {
if (children.size() > 0) return true;
else return false;
}
public String toString() {
return myCommonNoun.toString();
}
}
public class JSONContainer<T> {
private T myObject;
private ArrayList<JSONContainer<T>> children;
// public Class<T> typeParameterClass;
public JSONContainer() {
}
public JSONContainer(T anObject) {
myObject = anObject;
children = new ArrayList<JSONContainer<T>>();
}
/* public JSONContainer(T anObject, Class<T> typeParameterClass) {
myObject = anObject;
children = new ArrayList<JSONContainer<T>>();
this.typeParameterClass = typeParameterClass;
}
*/
public void addChildren(ArrayList<JSONContainer<T>> newChildren) {
children.addAll(newChildren);
}
public void addChild(T concept) {
children.add(new JSONContainer<T>(concept));
}
public ArrayList<JSONContainer<T>> getChildren() {
return children;
}
public T getValue() {
return myObject;
}
public boolean hasChildren() {
if (children.size() > 0) return true;
else return false;
}
public String toString() {
return myObject.toString();
}
}
Additional classes requested:
public class CommonNoun extends Concept {
/**
*
*/
private static final long serialVersionUID = 6444629581712454049L;
public CommonNoun() {
super();
}
public CommonNoun(String name, ConceptID cidIn) {
super(name, cidIn);
this.form = ConceptDefs.COMMON_NOUN;
}
}
public class Concept implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2561549161503772431L;
private ConceptID cid = null;
private final String name;
Integer form = 0;
// ArrayList<ProperRelationship> myRelationships = null;
/* #Deprecated
public Concept(String name) {
this.name = name;
}*/
public Concept() {
name = "";
}
public Concept(String name, ConceptID cidIn) {
// this(name);
this.name = name;
cid = cidIn;
}
/*
* This should be over-ridden by any subclasses
*/
public Integer getForm() {
return form;
}
public ConceptID getID() {
return cid;
}
public void setID(ConceptID cidIn) {
cid = cidIn;
}
//this doesn't make any sense. Throw exception?
public String getName() {
return name;
}
public boolean isCommon() {
return true;
}
/**
*
* #return
*/
#Override
public String toString() {
return getName() + "(" + cid.toString() + ")";
}
public boolean equals(Concept other) {
return ((getID().equals(other.getID())));
}
}
public class ConceptID implements Serializable {
long oid;
public ConceptID() {
oid = -1;
}
public ConceptID(long oid) {
this.oid = oid;
}
public long getValue() {
return oid;
}
/**
*
* #return
*/
#Override
public String toString() {
return Long.toString(oid);
}
public Long toLong() {
return Long.valueOf(oid);
}
public boolean equals(ConceptID other) {
return (oid == other.getValue());
}
/**
* Factory model for generating ConceptIDs
*
* This one is here as a convenience as many IDs come in as a String from web POSTs
* #param idAsString
* #return
*/
static public ConceptID parseIntoID(String idAsString) {
ConceptID returnID = null;
try {
returnID = new ConceptID( Long.parseLong(idAsString) );
} catch (Exception e) {
System.err.println("Expected the string, " + idAsString + ", to be Long parsable.");
e.printStackTrace();
}
return returnID;
}
TL;DR:
Proposed Fix…
System.out.println( new Json( ).toJson( new JSONContainer<>( ... ) ) to see the correct string format of a JSONContainer's JSON.
Make sure your result input argument to Json.fromJson(Class<T>, String) is in the same format printed out in 1.
e.g. {myObject:{class:CommonNoun,cid:{oid:139},name:Jada Pinkett Smith,form:69},children:[{myObject:{class:CommonNoun,cid:{oid:666},name:Jaden Pinkett Smith,form:-666},children:[]},{myObject:{class:CommonNoun,cid:{oid:69},name:Willow Pinkett Smith,form:69},children:[]}]}
The long answer…
„My IDE doesn't care for this phrasing, noting:“
Type safety: The expression of type JSONContainer needs unchecked conversion to conform to JSONContainer
It's the compiler warning you about heap pollution. The IDE merely translated this compiler warning (which is what you'd see on the command line)…
...Communicator.java uses unchecked or unsafe operations.
...Recompile with -Xlint:unchecked for details.
…into the more user-friendly message the IDE showed you.
It is only a warning; not an error. To make that warning go away, change this: JSONContainer<CommonNoun> typeContainer = ... to this: JSONContainer typeContainer = ...
„When executed, my err log reads:“
result = {"myObject":{"cid":{"oid":129},"name":"technology","form":1},"children":[]}
com.badlogic.gdx.utils.SerializationException: Field not found: cid (java.lang.Object)...
The most likely cause of that error is — like the error message says — either your JSONContainer class or your CommonNoun class does not have the cid field that is present in the JSON string you're trying to deserialize.
I was able to reproduce that error with this…
...
private static final String JADEN_AS_JSON = "{jden:{class:CommonNoun,person:Jaden,place:Hollywood,thing:HashBeen}}";
private static final String JADEN_FAILS_AS_ACTOR = "{jden:{class:CommonNoun,person:Jaden,place:Hollywood,thing:HasBeen, cid:{oid:129} }}";
static public void main( String ... args ){
out.printf( "%1$22s%n", "foo");
JSONContainer< CommonNoun > wtf = new JSONContainer< > ( );
CommonNoun wtBrattyF = new CommonNoun( "Jaden Pinkett Smith", "Hollywood", "HasBeen" );
wtf.setJden( wtBrattyF );
out.printf( "%1$42s%n", wtf );
Json jden = new Json();
out.printf("%1$59s%n", jden.toJson( wtf ) );
JSONContainer wtReifiableF = jden.fromJson(JSONContainer.class, JADEN_AS_JSON); /* This is fine */
out.printf("%1$59s%n", jden.toJson( wtReifiableF ) );
JSONContainer/*< CommonNoun >*/ wtUnReifiableF = jden.fromJson( JSONContainer.class, JADEN_AS_JSON );
wtUnReifiableF = jden.fromJson( JSONContainer.class, JADEN_FAILS_AS_ACTOR ); /* This causes the error you reported */
}
...
Early on it succeeds; but later on it fails…
JSONContainer [ jden: CommonNoun [ person: Jaden Pinkett Smith, place: Hollywood, thing: HasBeen ] ]
{jden:{class:CommonNoun,person:Jaden Pinkett Smith,place:Hollywood,thing:HasBeen}}
{jden:{class:CommonNoun,person:Jaden,place:Hollywood,thing:HashBeen}}
Exception in thread "main" com.badlogic.gdx.utils.SerializationException: Field not found: cid (CommonNoun)
Serialization trace:
{}.jden.cid
jden (JSONContainer)
at com.badlogic.gdx.utils.Json.readFields(Json.java:893)
at com.badlogic.gdx.utils.Json.readValue(Json.java:1074)
at com.badlogic.gdx.utils.Json.readFields(Json.java:902)
at com.badlogic.gdx.utils.Json.readValue(Json.java:1074)
at com.badlogic.gdx.utils.Json.fromJson(Json.java:829)
at DeduperAnswer.main(DeduperAnswer.java:33)
I have now confirmed by experimentation that given the existence of a Cid class…
public class Cid {
int oid;
/* ... getter and setter elided ... */
}
… And given the existence of a CommonNoun class that HAS A Cid…
public class CommonNoun {
Cid cid;
String name;
int form;
/* ... getters and setters elided ... */
}
…Then trying to deserialize a JSONContainer from a result that has the following value, will produce the exact same error you originally reported…
result = {"myObject":{"cid":{"oid":129},"name":"technology","form":1},"children":[]}
If your actual CommonNoun class is implemented like my stand-in above (with a Cid field), then you need to retry your json.fromJson(Class<?>, String) call with your result string formatted like…
{myObject:{class:CommonNoun,cid:{oid:139},name:Jada Pinkett Smith,form:69},children:[{myObject:{class:CommonNoun,cid:{oid:666},name:Jaden Pinkett Smith,form:-666},children:[]},{myObject:{class:CommonNoun,cid:{oid:69},name:Willow Pinkett Smith,form:69},children:[]}]}
To keep things as simple as I can, I am trying to pass an ArrayList holding values used for a method in a separate class in my program. The issue is that whatever I tweak, the values held in retailerID and prodCat never seem to make it to the subscribe method in the other class as previously mentioned. Here is the snippet I am trying to overcome at the moment. Please ingore the commented out portions as those were previous attempts I've yet to get rid of.
public class SupplyDemand {
Producer nProducer = new Producer();
Retailer nRetailer = new Retailer();
Broker nBroker = new Broker();
ArrayList<String> output = new ArrayList<String>();
ArrayList<String> inputCommand = new ArrayList<String>();
/**
* Class constructor - you may set up any needed objects and data here. Specification of constructor is optional - it is acceptable if you leave it blank.
*/
public SupplyDemand() {
}
/**
* This method accepts a single command and carry out the instruction given. You do not need to (and probably shouldn't) do everything in this method - delegate responsibilities to other classes.
*/
public void processInput(String command) {
//command.toLowerCase();
//String str[] = command.split(",");
inputCommand.add(command.toLowerCase());
//inputCommand = Arrays.asList(str);
if(inputCommand.contains("subscribe")){
String retailerID = inputCommand.get(1);
String prodCat = inputCommand.get(2);
nRetailer.subscribe(retailerID, prodCat);
}
else if(inputCommand.contains("unsubscribe")){
String retailerID = inputCommand.get(1);
String prodCat = inputCommand.get(2);
nRetailer.unsubscribe(retailerID, prodCat);
}
else if(inputCommand.contains("publish")){
String producerID = inputCommand.get(1);
String prodCat = inputCommand.get(2);
String brand = inputCommand.get(3);
nProducer.publish(brand, prodCat, producerID);
nBroker.checkMatch();
}
else{
}
//nBroker.checkMatch();
}
/**
* After each round of execution, this method would be called to fetch all output lines, if there are any. The lines must be ordered by the time they are received.
*/
public ArrayList<String> getAggregatedOutput() {
output = nRetailer.subscribeList;
return output;
}
/**
* Finally, this method would be called to clear all saved information in the system, so that information from previous round would not be carried to next round. After calling this method the system should be effectively starting anew.
*/
public void reset() {
nRetailer.subscribeList.clear();
nProducer.producerList.clear();
nBroker.buildMatch.clear();
}
}
Here is the Retailer class with the subscribe method and how I need to use the needed strings if its any help.
public class Retailer implements ISubscriber {
public String retailerID = " ";
public ArrayList<String> subscribeList = new ArrayList<String>();
/*/**
* #see SupplyDemand.ISubscriber#subscribe(String)
*/
public void subscribe(String retailerID, String prodCat) {
subscribeList.add("TEST1");
if(retailerID.equals(" ")){
subscribeList.add(retailerID);
subscribeList.add(prodCat);
}
else{
subscribeList.add("TEST2");
}
}
/*/**
* #see SupplyDemand.ISubscriber#unsubscribe(String)
*/
public void unsubscribe(String retailerID, String prodCat) {
int removeRetailer = subscribeList.indexOf(retailerID);
int removeProdCat = subscribeList.indexOf(removeRetailer + 1);
subscribeList.remove(removeProdCat);
subscribeList.remove(removeRetailer);
}
}
Item searchByPattern(String pat)
{
for(Iterator iter = items.iterator(); iter.hasNext(); )
{
Item item = (Item)iter.next();
if ((xxxxxxxxxxxx).matches(".*"+pat+".*"))
{
return item;
}
}
}
The above code is part of a class from my java program
public class Item
{
private String title;
private int playingTime;
private boolean gotIt;
private String comment;
/**
* Initialise the fields of the item.
*/
public Item(String theTitle, int time)
{
title = theTitle;
playingTime = time;
gotIt = true;
comment = "";
}
public String getTitle() {
return title;
}
/**
* Enter a comment for this item.
*/
public void setComment(String comment)
{
this.comment = comment;
}
/**
* Return the comment for this item.
*/
public String getComment()
{
return comment;
}
/**
* Set the flag indicating whether we own this item.
*/
public void setOwn(boolean ownIt)
{
gotIt = ownIt;
}
/**
* Return information whether we own a copy of this item.
*/
public boolean getOwn()
{
return gotIt;
}
public int getPlayingTime()
{
return playingTime;
}
/**
* Print details about this item to the text terminal.
*/
public void print()
{
System.out.println("Title: " + title);
if(gotIt) {
System.out.println("Got it: Yes");
} else {
System.out.println("Got it: No");
}
System.out.println("Playing time: " + playingTime);
System.out.println("Comment: " + comment);
}
}
I want to access all the methods that return values from class Item and once it matches the statement in Item searchByPattern, it will return the object.
I knew that I can do it by or operator like item.getTitle().matches(".*"+pat+".*") ||item.getComment().matches(".*"+pat+".*")||.......
but is it possible to get the same result by using a method in (xxxxxxxxxx)?
This isn't directly possible to do, however there are a few things you can try (from easiest to hard):
Just check all String type methods yourself in your code.
Add a special method in Item that does the match so Item class can decide itself when it matches. Here again you will need to make check all Strings manually.
You could add a method to Item that returns all methods that return a String as functions:
Code:
List<Supplier<String>> getAllStringMethods() {
return Arrays.asList(this::getComment, this::getTitle);
}
You can then use that to check all Strings one at a time by doing:
boolean match = item.getAllStrings().stream()
.map(Supplier::get)
.anyMatch(s -> s.matches("pattern"));
You can use Reflection to inspect the Item.class to find all methods that take no parameters and return a String, and then invoke them one by one. This is complicated and slow, and beyond the scope of this answer to explain further.
Hello ive added two new functions to the implementation of an interface.
this is the implementation file...
import au.edu.uow.Collection.Album;
import java.util.ArrayList;
public class CDAlbum implements Album {
private String Title;
private String Genre;
private String Artist;
private String MediaType;
private ArrayList<String> trackList;
public CDAlbum(String TempTitle, String TempGenre, String TempArtist, ArrayList<String> TempTracklist, String TempMediaType){
//Set initail variable values
Title = TempTitle;
Genre = TempGenre;
Artist = TempArtist;
trackList = TempTracklist;
MediaType = TempMediaType;
}
//Accessor Functions
public String getMediaType(){
//Return Media Type
return MediaType;
}
public String getTitle(){
//Return Title
return Title;
}
public String getGenre(){
//Return Genre
return Genre;
}
public String getArtist(){
//Return Artist
return Artist;
}
public ArrayList<String> getTrackList(){
//Return Tracklist
return trackList;
}
}
The bottom two functions are the added functions( getArtist(), getTrackList())
the problem im having is that when i try to call these functions from a class file it give me the following errors.
./au/edu/uow/UserInterface/UserInterface.java:95: cannot find symbol
symbol : method getArtist()
location: interface au.edu.uow.Collection.Album
System.out.println(albumCollection.get(number).getArtist());
^
./au/edu/uow/UserInterface/UserInterface.java:98: cannot find symbol
symbol : method getTrackList()
location: interface au.edu.uow.Collection.Album
ArrayList<String> trackList = albumCollection.get(number).getTrackList();
When i call the functions
import au.edu.uow.Collection.Album;
System.out.println(albumCollection.get(number).getArtist());
//Access the track titles
ArrayList<String> trackList = albumCollection.get(number).getTrackList();
//Output collection
int arrayListSize = trackList.size();
for(int i = 0; i < arrayListSize; i++)
{
System.out.println( i + ": " + trackList.get(i));
}
Album specifies neither getArtist nor getTrackList:
public interface Album {
/**
* This method returns the media type of the album.
* #return the media type of the album, either CD or DVD
* #see #getTitle()
* #see #getGenre()
*/
String getMediaType();
/**
* This method returns the title of the album.
* #return the title of the album
* #see #getMediaType()
* #see #getGenre()
*/
String getTitle();
/**
* This method returns the genre of the album.
* #return the genre of the album
* #see #getTitle()
* #see #getMediaType()
*/
String getGenre();
}
... only CDAlbum does.
You can determine whether the Album is a CDAlbum or DVDAlbum by checking Album.getMediaType; then, if it is a CD, you can cast to CDAlbum and invoke getArtist and getTrackList then.
for (final Album album : albumCollection) {
final String type = album.getMediaType();
System.out.print(type + " album: " + album.getTitle()
+ " (" + album.getGenre() + ") - ");
if (type.equals("CD")) {
final CDAlbum cd = (CDAlbum) album;
System.out.println(cd.getArtist());
int n = 0;
for (final String track : cd.getTrackList()) {
System.out.printf("#%2d - %s\n", ++n, track);
}
} else {
final DVDAlbum dvd = (DVDAlbum) album;
System.out.println(dvd.getDirector());
System.out.println(dvd.getPlotOutline());
}
}
Is Album the return type of albumCollection.get(number)? If so, then you need to add getArtist and getTrackList method into your interface as well.
When you add new method in your interface you must implement in your implementation class.
check the type of albumCollection.get(number)
if albumCollection.get(number) return Album then you can call getArtist()
Create a super class say for example MasterAlbums and extend your CDAlbum and DVDAlbum from it.Place the methods getArtist() & getTrackList() in the super class.Do not override it in the subclasses.Now when you call System.out.println(albumCollection.get(number).getArtist()); , It will refer to the superclass method and your artist & tracklist will be printed.