I posted a question in the past but didn't get any response so I'm assuming my question wasn't clear.
Can we define new Object[3][] without defining number of columns?
Hoping following code is more readable and easy to understand.
Question:
Why is retval[0] always null?
Please help.
Thanks,
package YTesting1.YTesting1;
import org.testng.annotations.Test;
public class Test1 {
#Test
public void MyTest() {
Object[][] retval = new Object[1][];
String mm = "Hello";
String o = "World";
String s = "Yeaah";
(new Object[1])[0] = new Test2(mm, o, s);
retval[0] = new Object[1];
System.out.println("retval = " +retval[0]);
}
}
package YTesting1.YTesting1;
public class Test2 {
private String str1 = "";
private String str2 = "";
private String str3= "";
public Test2(String lstr1, String lstr2, String lstr3){
this.str1 = lstr1;
this.str2 = lstr2;
this.str3 = lstr3;
}
}
retval[0] is not null, it is assigned to an empty array of Object.
It is possible to assign to retval[0] some another array and populate it without indicating the number of columns
public static void main(String ... args) {
Object[][] retval = new Object[1][];
String mm = "Hello";
String o = "World";
String s = "Yeaah";
//(new Object[1])[0] = new Test2(mm, o, s);
retval[0] = new Object[1];
System.out.println("retval[0] = " + retval[0]);
System.out.println("retval[0][0] = " +retval[0][0]);
System.out.println("retval = " + Arrays.deepToString(retval));
retval[0] = new String[] { // 3-element string array
mm, o, s
};
System.out.println("retval[0] = " + retval[0]);
System.out.println("retval[0][0] = " +retval[0][0]);
System.out.println("retval = " + Arrays.deepToString(retval));
}
Output:
retval[0] = [Ljava.lang.Object;#5479e3f
retval[0][0] = null
retval = [[null]]
retval[0] = [Ljava.lang.String;#66133adc
retval[0][0] = Hello
retval = [[Hello, World, Yeaah]]
Related
I am trying to read an input file. Each value of the input file is inserted into the TreeMap as
If word is not existing: Insert the word to the treemap and associate the word with an ArrayList(docId, Count).
If the Word is present in the TreeMap, then check if the current DocID matches within the ArrayList and then increase the count.
THe
For the ArrayList, I created another class as below:
public class CountPerDocument
{
private final String documentId;
private final int count;
CountPerDocument(String documentId, int count)
{
this.documentId = documentId;
this.count = count;
}
public String getDocumentId()
{
return this.documentId;
}
public int getCount()
{
return this.count;
}
}
After that, I am trying to print the TreeMap into a text file as <DocID - Count>
Not sure what I am doing wrong here, but the output I get is as follows:
The Stem is todai:[CountPerDocument#5caf905d, CountPerDocument#27716f4, CountPerDocument#8efb846, CountPerDocument#2a84aee7, CountPerDocument#a09ee92, CountPerDocument#30f39991]
Wondering if anyone can guide me what i am doing wrong and if my method isn't correct what am i supposed to do?
public class StemTreeMap
{
private static final String r1 = "\\$DOC";
private static final String r2 = "\\$TITLE";
private static final String r3 = "\\$TEXT";
private static Pattern p1,p2,p3;
private static Matcher m1,m2,m3;
public static void main(String[] args)
{
BufferedReader rd,rd1;
String docid = null;
String id;
int tf = 0;
//CountPerDocument cp = new CountPerDocument(docid, count);
List<CountPerDocument> ls = new ArrayList<>();
Map<String,List<CountPerDocument>> mp = new TreeMap<>();
try
{
rd = new BufferedReader(new FileReader(args[0]));
rd1= new BufferedReader(new FileReader(args[0]));
int docCount = 0;
String line = rd.readLine();
p1 = Pattern.compile(r1);
p2 = Pattern.compile(r2);
p3 = Pattern.compile(r3);
while(line != null)
{
m1 = p1.matcher(line);
m2 = p2.matcher(line);
m3 = p3.matcher(line);
if(m1.find())
{
docid = line.substring(5, line.length());
docCount++;
//System.out.println("The Document ID is :");
//System.out.println(docid);
line = rd.readLine();
}
if(m2.find()||m3.find())
{
line = rd.readLine();
}
else
{
if(!(mp.containsKey(line))) // if the stem is not on the TreeMap
{
//System.out.println("The stem is not present in the tree");
tf = 1;
ls.add(new CountPerDocument(docid,tf));
mp.put(line, ls);
line = rd.readLine();
}
else
{
if(ls.indexOf(docid) > 0) //if its last entry matches the current document number
{
//System.out.println("The Stem is present for the same docid so incrementing docid");
tf = tf+1;
ls.add(new CountPerDocument(docid,tf));
line = rd.readLine();
}
else
{
//System.out.println("Stem is present but not the same docid so inserting new docid");
tf = 1;
ls.add(new CountPerDocument(docid,tf)); //set did to the current document number and tf to 1
line = rd.readLine();
}
}
}
}
rd.close();
System.out.println("The Number of Documents in the file is:"+ docCount);
//Write to an output file
String l = rd1.readLine();
File f = new File("dictionary.txt");
if (f.createNewFile())
{
System.out.println("File created: " + f.getName());
}
else
{
System.out.println("File already exists.");
Path path = Paths.get("dictionary.txt");
Files.deleteIfExists(path);
System.out.println("Deleted Existing File:: Creating New File");
f.createNewFile();
}
FileWriter fw = new FileWriter("dictionary.txt");
fw.write("The Total Number of Stems: " + mp.size() +"\n");
fw.close();
System.out.println("The Stem is todai:" + mp.get("todai"));
}catch(IOException e)
{
e.printStackTrace();
}
}
}
You didn't define the function String toString() in your class CountPerDocument. So, when you try to print a CountPerDocument variable, the default printed value is CountPerDocument#hashcode.
To decide how to represent a CountPerDocument variable in your code, add in your class the next function:
#Override
public String toString() {
return "<" + this.getDocumentId() + ", " + this.getCount() + ">";
}
Try to override toString method in CountPerDocument. Something like this:
public class CountPerDocument
{
private final String documentId;
private final int count;
CountPerDocument(String documentId, int count)
{
this.documentId = documentId;
this.count = count;
}
public String getDocumentId()
{
return this.documentId;
}
public int getCount()
{
return this.count;
}
#Override
public String toString() {
return documentId + "-" + count;
}
}
I want to ask the user for a message:
"Enter a message in the following format: "TO FROM MESSAGE : KEY"
Example input from user:
1 2 hey there how are you : bubble123
Then, I want to have the SecureMessage class return the message. However, I do not know how to create a String of the message part, as the getMessage() message requires a String assigned to it.
The SecureMessage class should not have any mutators in it. All fields in SecureMessage are set from the Message class.
public class SecureMessage {
private String message;
private String sourceName;
private String destName;
private String key;
public SecureMessage(String message, String sourceName, String destName, String key){
this.message = message;
this.sourceName = sourceName;
this.destName = destName;
this.key = key;
}
public String getMessage(String key){
return message + " from SecureMessage class";
}
public String getSourceName(){
return sourceName + " from SecureMessage class";
}
public String getDestName(){
return destName + " from SecureMessage class";
}
}
import java.util.ArrayList;
import java.util.Scanner;
public class Message {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String message = "blank", sourceName = "blank", destName = "blank", key = "blank", messageInput, userMessageDetails;
ArrayList<String> messageInputList = new ArrayList<>();
System.out.println("Enter message in form TO FROM MESSAGE : KEY \nExample --- 1 2 hey there how are you? : bubble123");
userMessageDetails = keyboard.nextLine();
String str = userMessageDetails;
String[] tokens = str.split(" ");
for(String s : tokens){
messageInputList.add(s);
}
System.out.println(messageInputList);
System.out.println("");
int x = messageInputList.size();
destName = messageInputList.get(0);
sourceName = messageInputList.get(1);
key = messageInputList.get(x-1);
//--this is where I am lost, because I need to pass a string to the SecureMessage getMessage() method---
// message = ???;
// I found out how to print the items, however this is not a string...
// for(int i = 2; i <= (x-3); i++){
// System.out.print(messageInputList.get(i) + " ");
// }
//------------------------------------------------------------------------------------------------------
SecureMessage secMsg = new SecureMessage(message, sourceName, destName, key);
System.out.println(secMsg.getDestName());
System.out.println(secMsg.getSourceName());
System.out.println(secMsg.getMessage(key));
}
}
This should do it:
message = String.join(" ", messageInputList.subList(2, x-2));
So for what I see, as you split by " ", then you will have your message split between messageInputList.get(2) and messageInputList.get(x-3).
The easy way is having a for and concatenate strings. Something like:
String s_message = "";
for(int i = 2; i <= (x-3); i++){
s_message = s_message + messageInputList.get(i) + " ";
}
message = IntStream.range(2, x - 2)
.mapToObj(messageInputList::get)
.collect(Collectors.joining(" "));
This will collect the elements from your messageInputList from index 2 to x-2 and collect them to a singular String message which you can pass to your SecureMessage class.
I think it could be much more simplier:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter message data.");
System.out.println("-------------------");
System.out.print("Destination name: ");
String destName = scan.next();
System.out.print("Source name: ");
String sourceName = scan.next();
System.out.print("Key: ");
String key = scan.next();
System.out.println("Message (multi-line, double ENTER to finish):");
scan.useDelimiter("\n\n\n");
String message = scan.next().trim();
SecureMessage secMsg = new SecureMessage(message, sourceName, destName, key);
System.out.println(secMsg.getDestName());
System.out.println(secMsg.getSourceName());
System.out.println(secMsg.getMessage(key));
}
Is their an easy way to pass the variables and arrays between these methods without having a super long method signature? Currently I am using these statics but I know that's not the "correct" way of doing it but if I pass them in the signature it starts to make everything look ugly. So what would be the "correct" way to pass the variables like lastName, firstName, and role?
// Program wide variables
//static String firstName; // First name from the file
static String lastName; // Last name from the file
static String username; // Username
static String password;
static String role;
static String email;
static String answersFile; // Answers file in use with path and ext
static String[] answeredQ = new String[questAsks]; // Recording the question asked
static Boolean[] answeredA = new Boolean[questAsks]; //Recording users answer
static Boolean[] answeredC = new Boolean[questAsks]; //Recording the correct answer
public static void main(String Args[]) throws FileNotFoundException, IOException {
// Main method that contains major control functions; a quick summary of the program; magic
}
public static void quiz(String testType) throws HeadlessException, IOException {
String testBankFile = path + testType + ".txt";
Random rand = new Random();
int questionCount = 0, right = 0, wrong = 0;
long startTime = System.currentTimeMillis(); // Setting the start time in milliseconds
while (questionCount < questAsks) { // Loop that will ask all the questions
int r = rand.nextInt(getLines(testBankFile));
boolean ans = promptQuestion(read(r, testBankFile), questionCount + 1); // For some reason this makes it work
answeredQ[questionCount] = read(r, testBankFile);
answeredA[questionCount] = ans;
answeredC[questionCount] = parseA(read(r, answersFile));
if (ans != parseA(read(r, answersFile))) {
wrong++;
} else if (ans == parseA(read(r, answersFile))) {
right++;
}
questionCount++;
}
JOptionPane.showMessageDialog(null, "You got " + wrong + " wrong and " + right + " correct.");
long endDiff = (System.currentTimeMillis() - startTime);
makeReport(firstName, lastName, username, printTime(endDiff), testType, right);
}
// Generates a report report(first, last, score, time, array of answers)
public static void makeReport(String first, String last, String user, String time, String testType, int score) throws IOException {
DateFormat dateF = new SimpleDateFormat(dateFormat);
Date date = new Date();
String fileName = user + "_COSC236_Quiz_" + dateF.format(date) + ".txt";
File file = new File(fileName);
file.createNewFile();
FileWriter out = new FileWriter(fileName);
double percent = (((double) score) / ((double) questAsks) * 100);
out.write("Name: " + first + " " + last + "\n");
out.write("Score: " + percent + "%\n");
out.write("Elapsed time: " + time + "\n");
out.write("Test type: " + testType + "\n");
out.write("---------------------------------------------------------------------\n");
out.write(" Users\tCorrect\tQuestion\n");
for (int i = 0; i < answeredQ.length; i++) {
out.write(i + 1 + ".) ");
out.write(answeredA[i].toString() + "\t");
out.write(answeredC[i].toString() + "\t");
out.write(answeredQ[i] + "\n");
}
out.close();
}
// Boolean login method | login(tries allowed, source file)
public static void login(int tries, String source) throws FileNotFoundException, IOException {
String[] loginInfo;
boolean invalid = false;
for (int x = 0; x < tries; x++) {
invalid = false;
loginInfo = promptLogin();
if (loginInfo[0].toLowerCase().equals("done")) {
System.exit(0);
}
for (int i = 0; i < getLines(source); i++) {
StringTokenizer st = null;
st = new StringTokenizer(read(i, source));
String user = st.nextToken();
String pass = st.nextToken();
if (user.equals(loginInfo[0])) {
if (pass.equals(loginInfo[1])) {
username = loginInfo[0];
password = loginInfo[1];
firstName = st.nextToken();
lastName = st.nextToken();
email = st.nextToken();
role = st.nextToken();
if (role.toLowerCase().equals("instructor")) {
promptInstructor();
JOptionPane.showMessageDialog(null, exitedInstructorMode);
break;
} else {
run();
}
} else {
invalid = true;
}
} else {
invalid = true;
}
}
if(invalid) {
JOptionPane.showMessageDialog(null, invalidLogin);
}
}
JOptionPane.showMessageDialog(null, tooManyAttempts);
}
}
Why not just make a class that holds the values that you need to pass around
Use OOP. Create clss to you object
example:
class User{
String lastName;
String username;
String password;
String role;
String email;
...
public static User login(int tries, String source) throws FileNotFoundException, IOException {
//this you read User param and add new User
return user;
}
}
And now, where you need lastName, username, password, role or email, you can
pass User instance
public class TagHandler {
private final String START = "<START ";
private final String END = "<END ";
public String handleTag(String buf, String[] attrList) {
String startPattern1 = START+attrList[0]+">";
String endPattern1 = END+attrList[0]+">";
String startPattern2 = START+attrList[1]+">";
String endPattern2 = END+attrList[1]+">";
String startPattern3 = START+attrList[2]+">";
String endPattern3 = END+attrList[2]+">";
String startPattern4 = START+attrList[3]+">";
String endPattern4 = END+attrList[3]+">";
String startPattern5 = START+attrList[4]+">";
String endPattern5 = END+attrList[4]+">";
String extract1 = new String(buf);
String extract2 = new String(buf);
String extract3 = new String(buf);
String extract4 = new String(buf);
String extract5 = new String(buf);
extract1 = extract1.substring(extract1.indexOf(startPattern1)+startPattern1.length(), extract1.indexOf(endPattern1));
extract2 = extract2.substring(extract2.indexOf(startPattern2)+startPattern2.length(), extract2.indexOf(endPattern2));
extract3 = extract3.substring(extract3.indexOf(startPattern3)+startPattern3.length(), extract3.indexOf(endPattern3));
extract4 = extract4.substring(extract4.indexOf(startPattern4)+startPattern4.length(), extract4.indexOf(endPattern4));
extract5 = extract5.substring(extract5.indexOf(startPattern5)+startPattern5.length(), extract5.indexOf(endPattern5));
String s = ("BLOPABP"+extract1) + ("\nBLOPCALL"+extract2) +("\nBLOPEXP"+extract3) +("\nBLOPHEAD"+extract4)+("\nBLOPMAJ"+extract5);
return s;
}
How would I tidy up the code above into some sort of loop? Basically I have a file that i'm reading and extract the data within the tags and I'm passing the tags into this TagHandler method and returning the extracted data as a string with the tag headers without the "< START >" and "< END TAG"> leaving only the header on the start tag.
Here you go. This should do what you want.
public class TagHandler {
private final String START = "<START ";
private final String END = "<END ";
public String handleTag(String buf, String[] attrList) {
String[] blop = {"BLOPABP", "BLOPCALL", "BLOPEXP", "BLOPHEAD", "BLOPMAJ"};
String s = "";
for (int i = 0; i < attrList.length; i++) {
String startPattern = START+attrList[i]+">";
String endPattern = END+attrList[i]+">";
String extract = buf.substring(buf.indexOf(startPattern)+startPattern.length(), buf.indexOf(endPattern));
s += blop[i]+extract;
if (i < attrList.length-1) {
s += "\n";
}
}
return s;
}
}
Look out for an out of bounds exception, if attrList has more than 5 elements.
You can try something like this, optimize it if you can :
public String handleTag(String buf, String[] attrList) {
StringBuilder temp = new StringBuilder();
final String[] prefix = {"BLOPABP","\nBLOPCALL","\nBLOPEXP",
"\nBLOPHEAD","\nBLOPMAJ"};
for(int i=0;i<attrList.length;i++){
String startPattern = START+attrList[i]+">";
String endPattern = END+attrList[i]+">";
String extract = new String(buf);
extract = extract.substring(
extract.indexOf(startPattern)+startPattern.length(),
extract.indexOf(endPattern));
temp.append(prefix[i%5]+extract);
}
return temp.toString();
}
This should work. You can replace = new ArrayList<String> with = new ArrayList<>() if you're using java 7.
private final String START = "<START ";
private final String END = "<END ";
List<String> startPatterns = new ArrayList<String>();//can use ArrayList<> instead if java 1.7
List<String> stringExtracts = new ArrayList<String>();
final String[] tags = new String[]{"BLOPABP","\nBLOPCALL","\nBLOPEXP","\nBLOPHEAD","\nBLOPMAJ"};
public String handleTag(String buf, String[] attrList) {
int numPatterns = tags.length;
String s;
String extract = new String(buf);
for(int i=0; i<numPatterns; i++){
String startPattern = START+attrList[i]+">";
startPatterns.add(startPattern);
String endPattern = END+attrList[i]+">";
endPatterns.add(endPattern);
String extract = extract.substring(extract.indexOf(startPattern)+startPattern.length(), extract.indexOf(endPattern));
stringExtracts.add(extract);
s += tags[i] + extract;
}
return s;
}
This assumes that you need access to the individual startPatterns, endPatterns and stringExtracts again, not just s. If you only need s though then discard the ArrayLists - it will work like this:
private final String START = "<START ";
private final String END = "<END ";
final String[] tags = new String[]{"BLOPABP","\nBLOPCALL","\nBLOPEXP","\nBLOPHEAD","\nBLOPMAJ"};
public String handleTag(String buf, String[] attrList) {
int numPatterns = tags.length;
String s;
String extract = new String(buf);
for(int i=0; i<numPatterns; i++){
String startPattern = START+attrList[i]+">";
String endPattern = END+attrList[i]+">";
String extract = extract.substring(extract.indexOf(startPattern)+startPattern.length(), extract.indexOf(endPattern));
s += tags[i] + extract;
}
return s;
}
For example: { "primary:title":"Little Red Riding Hood"}
My Parser in Java (Android) is always getting stuck because of the colon between primary and title. I can parse anything else with ease, I just need help in this.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
TextView txtViewParsedValue;
private JSONObject jsonObject;
private JSONArray jsonArray;
String [] titles, links, mediaDescriptions, mediaCredits, descriptions, dcCreators, pubDates, categories;
String [] permalinks, texts; // guid
String [] rels, hrefs;
String [] urls, media, heights, widths; // media:content
String strParsedValue = "";
private String strJSONValue;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
strJSONValue = readRawTextFile(this, R.raw.jsonextract);
txtViewParsedValue = (TextView) findViewById(R.id.text_view_1);
try {
parseJSON();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void parseJSON() throws JSONException
{
txtViewParsedValue.setText("Parse 1");
jsonObject = new JSONObject(strJSONValue);
jsonArray = jsonObject.getJSONArray("item");
titles = new String[jsonArray.length()];
links = new String[jsonArray.length()];
permalinks = new String[jsonArray.length()];
texts = new String[jsonArray.length()];
mediaDescriptions = new String[jsonArray.length()];
mediaCredits = new String[jsonArray.length()];
descriptions = new String[jsonArray.length()];
dcCreators = new String[jsonArray.length()];
pubDates = new String[jsonArray.length()];
categories = new String[jsonArray.length()];
txtViewParsedValue.setText("Parse 2");
for (int i=0; i<jsonArray.length(); i++)
{
JSONObject object = jsonArray.getJSONObject(i);
titles[i] = object.getString("title");
links[i] = object.getString("link");
JSONObject guidObj = object.getJSONObject("guid");
permalinks[i] = guidObj.getString("isPermaLink");
texts[i] = guidObj.getString("text");
//mediaDescriptions[i] = object.getString("media:description");
//mediaCredits[i] = object.getString("media:credit");
// *** THE PARSER FAILS IF THE COMMENTED LINES ARE IMPLEMENTED BECAUSE
// OF THE : IN BETWEEN THE NAMES ***
descriptions[i] = object.getString("description");
//dcCreators[i] = object.getString("dc:creator");
pubDates[i] = object.getString("pubDate");
categories[i] = object.getString("category");
}
for (int i=0; i<jsonArray.length(); i++)
{
strParsedValue += "\nTitle: " + titles[i];
strParsedValue += "\nLink: " + links[i];
strParsedValue += "\nPermalink: " + permalinks[i];
strParsedValue += "\nText: " + texts[i];
strParsedValue += "\nMedia Description: " + mediaDescriptions[i];
strParsedValue += "\nMedia Credit: " + mediaCredits[i];
strParsedValue += "\nDescription: " + descriptions[i];
strParsedValue += "\nDC Creator: " + dcCreators[i];
strParsedValue += "\nPublication Date: " + pubDates[i];
strParsedValue += "\nCategory: " + categories[i];
strParsedValue += "\n";
}
txtViewParsedValue.setText(strParsedValue);
}
public static String readRawTextFile(Context ctx, int resId)
{
InputStream inputStream = ctx.getResources().openRawResource(resId);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
//text.append('\n');
}
} catch (IOException e) {
return null;
}
return text.toString();
}
For one, and to answer your question, there is no issue with JSONObject and the org.json.* classes parsing keys with colons in them if they're properly formed. The following unit test passed which means it was able to parse your example scenario:
public void testParsingKeysWithColons() throws JSONException {
String raw = "{ \"primary:title\":\"Little Red Riding Hood\"}";
JSONObject obj = new JSONObject(raw);
String primaryTitle = obj.getString("primary:title");
assertEquals("Little Red Riding Hood", primaryTitle);
}
Another suggestion is that using arrays of Strings for your data is clumsy and you'd be much better organized using a data structure to represent your objects. Instead of string arrays for titles, links, descriptions; use an object that has these properties and make a list of the objects. For example:
public class MyDataStructure {
public String title;
public String primaryTitle;
public String link;
public String mediaDescription;
public static class Keys {
public static String title = "title";
public static String primaryTitle = "primary:title";
public static String link = "link";
public static String mediaDescription = "media:description";
}
}
And then you can make a "translator" class that does all the parsing for you and returns a list of your object. This is much easier to work with and keep track of. You never have to think about data misaligning or having more or less data in one of your arrays than you expected. You also have a much easier time testing where the problem is if your input data is missing anything or any of your json is malformed.
public class MyDataStructureTranslator {
public static List<MyDataStructure> parseJson(String rawJsonData) throws JSONException {
List<MyDataStructure> list = new ArrayList<MyDataStructure>();
JSONObject obj = new JSONObject(rawJsonData);
JSONArray arr = obj.getJSONArray("item");
for(int i = 0; i < arr.length(); i++) {
JSONObject current = arr.getJSONObject(i);
MyDataStructure item = new MyDataStructure();
item.title = current.getString(MyDataStructure.Keys.title);
item.primaryTitle = current.getString(MyDataStructure.Keys.primaryTitle);
item.link = current.getString(MyDataStructure.Keys.link);
item.mediaDescription = current.getString(MyDataStructure.Keys.mediaDescription);
list.add(item);
}
return list;
}
}
Since Java identifiers cannot have colons, just specify a json property name that maps to the exact json name like:
#JsonProperty("primary:title")
public String primaryTitle;