• Post Reply Bookmark Topic Watch Topic
  • New Topic

Arraylist of objects created from text file information  RSS feed

 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need help making sense of an assignment with minimal instruction. In a previous assignment we had to make a class that could obtain info and create a Contact object. I did well on that assignment and got 100% no problem, however I'm absolutely lost on this extension of that previous assignment as I find the instructions to be very confusing. First I'll post my code for the past assignment and then the instruction for the new assignment. This is a console application, and thus far we've covered arrays, array lists, try-catch, switch statements, loops, if statements and all the basics such as that as well as delimiters and split. We've only just started to cover implementation, extends, and other keywords like that and I don't think we are to use that in this project. For the sake of trying not to make this longer than necessary I'll trim down comments to the bare minimum. Feel free to skip past all the code in the first three classes I've posted as it works just as it's supposed to, I'm only posting it for reference sake in relation to the information further down the page.


****Driver*****



****Contact*****



****Contact Type Enum*****


===========

****This is the full instruction for the part 2 extension*****
The driver class should have a main menu that includes at least the following choices.
1. Import contacts from a file
2. Create and add a new Contact to AddressBook
3. Edit an existing Contact and update the AddressBook
4. Remove a Contact from the AddressBook by name
5. Display all Contacts from the AddressBook
6. Find and display a Contact by name in the AddressBook
7. Display all Contacts of a given ContactType
8. Display all Contacts that are in a specified zip code
9. Sort the Contacts in the AddressBook by name
10. Exit

The AddressBook class should have at least the following private attributes, but you may add as many others as needed:
* ArrayList <Contact>
* A special Contact named owner that represents the individual owner of the AddressBook. This will be the user of the program who gives his/her name when welcomed to the program.

In addition to the usual constructors, getters, setters, and toString methods, the AddressBook class will need the methods required to support the functionality required in the driver (searching, sorting, retrieving a Contact, adding a Contact, and so forth).

Note: The AddressBook class contains a PRIVATE ArrayList<Contact>. Since the ArrayList is private, its methods are NOT ACCESSIBLE from the driver or any other class. You will need to add public methods such as get, set, size, and remove to AddressBook class so they can be used from outside of AddressBook to access the necessary features of the encapsulated ArrayList.

Test the program with at least 10 Contact objects of varying ContactTypes. Otherwise, you will not be assured that all sorting and searching methods have been completely tested. This information should be in a txt file that can be read in by the driver if that option is chosen. The user must be able to choose the file to be read in (using JFileChooser). If the contacts have been changed in any way, you are to write out the updated address book to a file (again using JFileChooser) before the program closes. In your design document, be sure to provide the complete list of Contact information to be used in testing.

You must handle all exceptions in processing. Simply adding a throws Exception clause to the methods inside the driver does not count as “handling the exceptions”.


I have created an AddressBook class and have a private attribute called owner of type Contact as well as an attribute called contacts which is an array list of type Contact. However there are several problems I'm having with this.

First, per the instructions, "owner" is supposed to be a special contact, and yet is only supposed to consist of a name obtained when the user enters their name upon starting the program, yet I don't have any constructors in the contact class that only accept a name and ignore the rest of the attributes. I could create a constructor like that I suppose, but isn't that bad form to make a constructor like that for just one special case rather than general purpose for creating multiple objects from that class? Is there some other way to make an object like that which would only contain one piece of information and exclude everything else?

Second, what would be the best way to use a JFileChooser with a console application that has a menu such as the one described? My initial thought was to use a switch case menu and put the logic for each condition inside of each case, but then I'm unsure as to where the data should be sent. My understanding is that AddressBook class is supposed to create an ArrayList of Contacts that will together form an address book. So currently I have something like this in the driver:



To create this in that manner would mean I would have to have such logic inside of each case statement to call to the appropriate methods as I'm not sure how else to go about this given the limitations of only having the four classes to work with. That makes me cringe, but since it's supposed to read input from a file I thought I would need to ask the user in the driver specific to the option they chose and then pass the file name to the addressbook since all the information that will be read from the file will then need to be passed to the Contact class' constructor in order to be made into a contact object. So once it's passed into the AddressBook I have a method that can read the contents of the file and assemble each line into an ArrayList of type String since there's really no way of knowing how many contacts a file could actually contain. So once each line is stored into an array list then I need to use another method to somehow take each item from that ArrayList and split at a delimiting pipe space character in the text file and then somehow pass each piece of information into the contact class constructor. I have no idea how to even go about passing an array of strings to the Contact class to be made into a Contact object and especially since one value that will be read in from the file is an Enum. Maybe I could use valueOf, but I'm not sure. Without hard coding all 9 indexes of the array of delimited strings into a call to the Contact constructor, how else might I pass the array of string data to the constructor, while also being mindful of the one Enum that would have to be dealt with as well? Sorry to make this so long, I'm just really confused with the instruction for this extension and am not sure if I'm just not fully thinking it through of it's just worded poorly or what. Any suggestions or help getting started in the right direction or ideas as to what I should consider putting where would be greatly appreciated.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
With your constructors you have a few options:

The reason I would choose option 3 is that if you keep your read/write file capability within the class then if you need to add a field you don't have to chase through all your code to find the places you'd need to change, it would all be in your AddressBook class.

Regarding your menu, I'd suggest making each option into its own method which would keep your switch() block nice and clean.

Because your AddressBook class wraps around the ArrayList your AddressBook class will need several methods, e.g. add(Contact contact), that don't do much other than calling the ArrayList methods.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
With regards to your enum, you'd need a way to convert your enum values to and from some sort of text representation for writing and reading a file. You could do this based on ordinal value but that seems a bit brittle because if you modify the enum list your file will be out of date. Better to write and read the enum value name.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Cross posted on
http://stackoverflow.com/questions/27311909/read-and-add-text-file-to-an-arraylist-of-object-in-java
Cross posting is acceptable on CodeRanch but you should be up front about it so that people don't duplicate effort.
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:Cross posted on
http://stackoverflow.com/questions/27311909/read-and-add-text-file-to-an-arraylist-of-object-in-java
Cross posting is acceptable on CodeRanch but you should be up front about it so that people don't duplicate effort.

Cross post? What are you talking about? That isn't my post if that's what you meant, unless you simply mean that it's a similar question, however I did search around to try to puzzle some of this out on my own, but with little success. I didn't even see that stack post you mentioned. Actually that post on stack looks like its from 2014.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:
Carey Brown wrote:Cross posted on
http://stackoverflow.com/questions/27311909/read-and-add-text-file-to-an-arraylist-of-object-in-java
Cross posting is acceptable on CodeRanch but you should be up front about it so that people don't duplicate effort.

Cross post? What are you talking about? That isn't my post if that's what you meant, unless you simply mean that it's a similar question, however I did search around to try to puzzle some of this out on my own, but with little success. I didn't even see that stack post you mentioned. Actually that post on stack looks like its from 2014.

My humble apologies.
 
Junilu Lacar
Sheriff
Posts: 11476
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Consider this: the previous assignment was to see if you knew how to chain constructors, which I guess you were able to demonstrate that you did. However, what you implemented doesn't make much sense. If you create a new contact without specifying any contact information, do you really want it to default to Bill Nye the Science Guy every time? If I were a user of that kind of program, I'd have some choice words for the programmer. If I created a new contact, I'd expect all the contact information to be empty, not initialized by default to that guy.

So, wouldn't it be reasonable to change your implementation of the no-argument constructor for this assignment, since the goals are different?

 
Junilu Lacar
Sheriff
Posts: 11476
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:I would have to have such logic inside of each case statement to call to the appropriate methods as I'm not sure how else to go about this given the limitations of only having the four classes to work with. That makes me cringe...

As well it should.  Given that you have at least 10 menu options, you're looking at a ginormous switch case with well over 400 lines of code! In a good program, 20 lines of code is pushing the limit of reasonable size of a method.

For professional work, the goal is to have about 1 to 5 lines of code on average, and definitely less than 20 lines if you have to push the limit. This is because if you have more than 20 lines, it becomes more and more difficult to read and understand what's going on in that method. For student work, I'd say that limit could be reasonably set to 30 lines of code. If you write more than that, then it's on the instructor's head because in my opinion, they should be teaching you not to write long, confusing code like that.

You already know how to write methods, so why not use methods to break up your program into smaller, more manageable chunks? If you think of your body as a program, imagine the horror of having organs that did multiple things like combining the functions of circulation, digestion, and speech into one organ. If that were the case, we'd all be spewing blood and cr*p every time we try to say something, right? Your body is a complex system but it works because it's well organized. Each part has its own little job to do, down to the tiniest bone in your ear that has a specific function to aid in giving you the ability to hear things. Likewise, your classes should be divided into small chunks of logic, each chunk "encapsulated" in a method whose name explains what is happening in it. Even a naive implementation of a menu such as yours that follows this principle would be less than 20 lines long:
 
Junilu Lacar
Sheriff
Posts: 11476
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:I have a method that can read the contents of the file and assemble each line into an ArrayList of type String since there's really no way of knowing how many contacts a file could actually contain. So once each line is stored into an array list then I need to use another method to somehow take each item from that ArrayList and split at a delimiting pipe space character in the text file

Do you really need to do it that way? I'd argue that you can do it that way but there's no need to make it so complicated. You have to set your foot down as to what the arrangement of the data in the text file should be. Otherwise, there's no limit to the number of variations you're going to have to contend with in your program. A common format to use is CSV (comma-separated values) with one line in the text file representing the data for one record, which is in this case is one contact. Each line must consistently have the same order of data elements. You decide what that order is and write your program accordingly.

Once you have that decision firmed up, then you can simply read each line in with a Scanner. You can then scan each line for the data items.

where the parseContactInfo() will use another scanner to read in each separate Contact field and populate a new Contact instance with that information.

Do you see how I'd break the task down to smaller, more manageable chunks again?

and then somehow pass each piece of information into the contact class constructor. I have no idea how to even go about passing an array of strings to the Contact class to be made into a Contact object and especially since one value that will be read in from the file is an Enum. Maybe I could use valueOf, but I'm not sure. Without hard coding all 9 indexes of the array of delimited strings into a call to the Contact constructor, how else might I pass the array of string data to the constructor, while also being mindful of the one Enum that would have to be dealt with as well?

All enum types have a built-in valueOf() method that will convert from String to the enum type. You just have to make sure your string values are exactly the same as the enum type names, including case. Enum type values are constants so they are usually declared as all uppercase. That's just a convention though, not a language requirement, but it's a convention that you don't appear to be following.
 
Junilu Lacar
Sheriff
Posts: 11476
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Note also that constructors and methods that have more than three or four parameters stink of complexity. When you get to a point where you're wanting to have more than four parameters in a constructor, you should start thinking about the Builder pattern.

That's much easier to read than a constructor call with 10 parameters
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:Do you really need to do it that way? I'd argue that you can do it that way but there's no need to make it so complicated. You have to set your foot down as to what the arrangement of the data in the text file should be. Otherwise, there's no limit to the number of variations you're going to have to contend with in your program. A common format to use is CSV (comma-separated values) with one line in the text file representing the data for one record, which is in this case is one contact. Each line must consistently have the same order of data elements. You decide what that order is and write your program accordingly.

Once you have that decision firmed up, then you can simply read each line in with a Scanner. You can then scan each line for the data items.

where the parseContactInfo() will use another scanner to read in each separate Contact field and populate a new Contact instance with that information.

Do you see how I'd break the task down to smaller, more manageable chunks again?


Still not sure I understand. I have no idea what CSV is and if we haven't been taught about it, then I'd probably get docked points for using it.

For this part of the project I had to make a text file so data looks like this:
Other|Bill Nye|4742 42nd Avenue|Seattle|WA|98116|2067159824|ScienceGuy@Nerd.com|SmartGuy.jpg


and because I have no idea what I'm doing or how this mess is supposed to work I have this jumble in my driver:


So now all the text data is stored into an array list line by line, but I have no idea how I'm supposed to break that apart. As for the constructor with numerous parameters, that's how it was supposed to be made. I've not heard of the Builder Pattern, and as mentioned before, if we haven't been taught about it, then generally we shouldn't use it else we may get docked points. If I were allowed to do this my way.....but that's neither here nor there unfortunately. I was also told not to use string builder because we've not learned about it yet, so I'm supposed to use loops to concatenate strings.
 
Knute Snortum
Sheriff
Posts: 4273
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Are the field separated by a literal pipe character (|)?  If so, try using String#split(regex).  The only tricky thing about that is that in a regex, the pipe character is a "metacharacter".  That means you'll have to escape it.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:Are the field separated by a literal pipe character (|)?  If so, try using String#split(regex).  The only tricky thing about that is that in a regex, the pipe character is a "metacharacter".  That means you'll have to escape it.


The class hasn't learned regex, so I doubt I'd be allowed to use it. Technically they don't even mention Regex until higher level courses.
 
Knute Snortum
Sheriff
Posts: 4273
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, since you can only use what you've learned, it stands to reason that you have learned what you need to solve the problem.  And since we don't know what you have and haven't learned, how can we help you?
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:
Knute Snortum wrote:Are the field separated by a literal pipe character (|)?  If so, try using String#split(regex).  The only tricky thing about that is that in a regex, the pipe character is a "metacharacter".  That means you'll have to escape it.


The class hasn't learned regex, so I doubt I'd be allowed to use it. Technically they don't even mention Regex until higher level courses.

Well, there's regular expressions that are so trivial that I would think that they would be exceptable. If you had a comma separated  file the regex would be ",", so simple as to not be an expression of any complexity.  Using commas as a separator in your file may be problematic if your data may accidentally contain a comma. This is where your choice of a pipe (|) character is not likely to fall victim to it's appearance in the data. The regex might have been simple as "|" except for the fact that, as mentioned, the pipe character needs to be escaped, hence "\\|".

I'm not sure how you'd like to procede, you could: 1) use String.split() which takes a trivial regex, or 2) you could set up a Scanner for the line with a delimiter, but that delimiter would need to be escaped as well, or 3) you could roll your own split() from scratch and use that.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You could roll your own using line.indexOf('|') and line.substring() inside a loop.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!