What data structure should I use in the case described below:
I have a simple bean:
public class Points {
private String name;
private String address;
private int phone;
private int coord1;
private int coord2;
//getters+setters
}
I would like to create several beans and store them in some sort of data structure.
And be able to search with two parameters - name and address.
For example, user types in "7" - and it gives him back several object,
which name or address contains this character?
What data structure should i use and how do i search through it?
If it is important, I actually need this to implement into my android app -
i would like to search through my points on the map
Also I do not want to create a database so far, as there are only 20 of them.
Thank you very much in advance.
Try java's collection, e.g. hashmap. Although I ran this on PC, for 10000 items, with search
returned 3440 results, it took 76ms.
class Points {
String name;
String address;
int phone;
int coord1;
int coord2;
// getters+setters
};
class PointsIdentifier {
private String name;
private String address;
public PointsIdentifier(String name, String address) {
this.name = name;
this.address = address;
}
public boolean contains(String seq) {
return name.contains(seq) || address.contains(seq);
}
#Override
public boolean equals(Object obj) {
Points other = (Points) obj;
return name.equals(other.name) && address.equals(other.address);
}
#Override
public int hashCode() {
return name.hashCode() + address.hashCode();
}
};
class PointsCollection {
private Map<PointsIdentifier, Points> map;
public PointsCollection() {
map = new HashMap<PointsIdentifier, Points>();
}
public void add(Points p) {
map.put(new PointsIdentifier(p.name, p.address), p);
}
public List<Points> findIdsContaining(String seq) {
List<Points> resultList = new ArrayList<Points>();
for (Entry<PointsIdentifier, Points> entry : map.entrySet()) {
if (entry.getKey().contains(seq)) {
resultList.add(entry.getValue());
}
}
// optionally cache result
return resultList;
}
}
public class Question_11881630 {
public static void main(String[] args) {
PointsCollection places = createCollection(10000);
System.out.println("Collection created");
String seq = "1";
System.out.format("Searching for: \"%s\"\n", seq);
List<Points> verifySearch = verifySearch(places, seq);
//show(verifySearch);
}
private static void show(List<Points> verifySearch) {
int i = 1;
for (Points p : verifySearch) {
System.out.println(i + ": " + p.name + ", " + p.address);
i++;
}
}
private static List<Points> verifySearch(PointsCollection places, String seq) {
long start = System.currentTimeMillis();
List<Points> searchResult = places.findIdsContaining(seq);
System.out.println("Search results: " + searchResult.size());
long end = System.currentTimeMillis();
System.out.println("Operation time: " + formatTime(end - start));
return searchResult;
}
private static String formatTime(long elapsed) {
return elapsed + " miliseconds";
}
private static PointsCollection createCollection(int number) {
PointsCollection coll = new PointsCollection();
while (number > 0) {
coll.add(createSamplePoint(number));
number--;
}
return coll;
}
private static Points createSamplePoint(int number) {
Points p = new Points();
p.name = "VeryVeryLongName: " + number;
p.address = "VeryVeryLongLongAddress: " + number;
p.coord1 = 123;
p.coord2 = 456;
return p;
}
}
A trie seems a good fit. It is an efficient data structure to find all strings with a certain prefix.
If you want to use one of the existing java collections instead, you can use a TreeSet, and its floor() method to get the element before the needed prefix - and then start iterating the set while it still matches.
If you are looking for search by substring, and not only prefix - you might want to use a suffix tree instead.
An (inefficient) alternative that uses java's existing containers - is to store all substrings of your keys in a Set or a Map, but it will require quadric amount of space.
Related
I am relatively new to programming and an working with setters and getters at the moment.
I have something set up where I have a student class that has information about said student, including their first, middle, and last name, their student ID, and their major.
I need to set it so that, if their student ID is less than zero, it automatically sets it to -1. I also need to set the major to undecided if they do not input anything.
I also need to override the toString method and print all of this information out.
I feel like I have the first part with the names down, I am not sure about the rest of it however. I am not sure how I am supposed to use the toString method while also using setters and getters.
Below is my Student class that does all of the work.
import java.util.Objects;
import java.util.Scanner;
public class Student {
String first;
String middle;
String last;
String major = "Undecided";
static int studentID = -1;
public Student(String first, String middle, String last) {
Objects.requireNonNull(first);
Objects.requireNonNull(last);
}
public void setFirst(String A) {
first = A;
}
public void setMiddle(String B) {
middle = B;
}
public void setLast(String C) {
last = C;
}
private String getFirst() {
return first;
}
private String getMiddle() {
return middle;
}
private String getLast() {
return last;
}
private String getMajor() {
return major;
}
public void setMajor(){
static void register(int a){
if (a < 0) {
studentID = a;
} else {
studentID = getID(a);
}
}
private static int getID(int a) {
if (studentIDInput < 0) {
studentID = -1;
} else {
studentID = a;
}
return studentID;
}
public static void main(String[] args) {
String first = "abc";
String middle = "def";
String last = "ghi";
Scanner sc = new Scanner(System.in);
String majorInput = sc.next();
int studentIDInput = sc.nextInt();
Student student1 = new Student(first, middle, last);
System.out.println(student1.getFirst().toString() + " " + student1.getMiddle().toString() + " " + student1.getLast().toString() + '\n' + "Major:" + " " + student1.getMajor().toString() + '\n' );
}
#Override
public String toString() {
return ;
}
}
I have also included the Driver class just for reference.
public class Driver {
static String first;
static String middle;
static String last;
public static void main(String[] args){
Student student1 = new Student(first, middle, last);
student1.setFirst("Mikayla");
student1.setMiddle("Rose");
student1.setLast("Knox");
}
}
You have this constructor:
public Student(String first, String middle, String last) {
Objects.requireNonNull(first);
Objects.requireNonNull(last);
}
It does its job of checking that first and last name are not null, but it does not do anything with the values besides checking. The constructor's job is to construct the object, i.e, initialize its member variables. When your constructor is done, you should have a usable object, without having to call any setters in it.
You need to add that:
public Student(String first, String middle, String last) {
Objects.requireNonNull(first);
Objects.requireNonNull(last);
this.first = first;
this.middle = middle;
this.last = last;
}
Note that you don't need to use setters here as code within the class can access member variables directly. You can use setters if you want, though.
As for toString: this is a method mainly used in debugging, and it displays some helpful information about the object it's called on. You could implement it like below, with a bit of ?: to make sure to only print the middle name if it's not null:
#Override
public String toString() {
return first + " " + (middle != null ? middle + " " : "") + last;
}
I'll leave it to you to also include major and ID.
On using a Scanner: You use a Scanner to get input from somewhere, like the from the user. You don't need it in toString or any setters or getters. These are all methods that should be very simple and not deal with I/O classes like Scanner.
If you are using constructors, you do not really need setters. Try something like this:
class Student {
private String first;
private String middle;
private String last;
private String major;
private int studentID;
public Student(String first, String middle, String last) {
this(first, middle, last, "undecided", -1);
}
public Student(String first, String middle, String last, String major, int studentID) {
this.first = first;
this.middle = middle;
this.last = last;
this.major = major;
this.studentID = studentID;
}
#Override
public String toString() {
return "first: " + first + "\nmiddle: " + middle + "\nlast: " + last + "\nmajor: " + major + "\nid: " _ studentID;
}
}
This way, when you create a new Student object with 3 parameters, the last 2 are automatically set to "undecided" and -1. If there is a case when you have the ID and not the major (or the other way around), you can add more constructors.
I'm currently looking through two very large lists of Peak Objects, by overriding the equals method and looping through the two lists, comparing every peak to every other peak. Is there a more efficient way of doing this? My lists can be ~10,000 elements, which means up to 10000 * 10000 comparisons.
The code for my peak object:
public class Peak extends Object{
private final SimpleIntegerProperty peakStart;
private final SimpleIntegerProperty peakEnd;
private final SimpleIntegerProperty peakMaxima;
private final SimpleIntegerProperty peakHeight;
private final SimpleIntegerProperty peakWidth;
private final SimpleStringProperty rname;
public Peak(int peakStart, int peakEnd, int peakMaxima, int peakHeight, String rname) {
this.peakStart = new SimpleIntegerProperty(peakStart);
this.peakEnd = new SimpleIntegerProperty(peakEnd);
this.peakMaxima = new SimpleIntegerProperty(peakMaxima);
this.peakHeight = new SimpleIntegerProperty(peakHeight);
this.peakWidth = new SimpleIntegerProperty(peakEnd - peakStart);
this.rname = new SimpleStringProperty(rname);
}
public String getRname() {
return rname.get();
}
public SimpleStringProperty rnameProperty() {
return rname;
}
public int getPeakWidth() {
return peakWidth.get();
}
public int getPeakHeight() {
return peakHeight.get();
}
public int getPeakStart() {
return peakStart.get();
}
public int getPeakEnd() {
return peakEnd.get();
}
public int getPeakMaxima() {
return peakMaxima.get();
}
#Override
public String toString() {
return "Peak{" +
"peakStart= " + peakStart.get() +
", peakEnd= " + peakEnd.get() +
", peakHeight= " + peakHeight.get() +
", rname= " + rname.get() +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Peak peak = (Peak) o;
if (!peakMaxima.equals(peak.peakMaxima)) return false;
return rname.equals(peak.rname);
}
#Override
public int hashCode() {
int result = peakMaxima.hashCode();
result = 31 * result + rname.hashCode();
return result;
}
}
And my loop for comparing the objects is here.
List<Peak> interestingPeaks = new ArrayList<>();
if(peakListOne != null && peakListTwo != null){
for(Peak peak : peakListOne){
for(Peak peak2 : peakListTwo){
if(peak.equals(peak2)){ //number one, check the rnames match
if((peak2.getPeakHeight() / peak.getPeakHeight() >= 9) || (peak.getPeakHeight() / peak2.getPeakHeight() >= 9)){
interestingPeaks.add(peak);
}
}
}
}
}
return interestingPeaks;
The code is basically matching the position of the maxima, and the rname , which is just a String. Then appending the peak to the interestingPeaks list if the height of one is a factor of 9x larger than the other.
Appreciate that if the two lists were sorted by maxima and name, you could simply make a single linear pass down both lists, and compare items side by side. If the two lists were in fact completely equal, then you would never find a pair from the two lists which were not equal.
List<Peak> p1;
List<Peak> p2;
p1.sort((p1, p2) -> {
int comp = Integer.compare(p1.getPeakMaxima(), p2.getPeakMaxima());
return comp != 0 ? comp : p1.getRname().compareTo(p2.getRname());
});
// and also sort the second list
Now we can just walk down both lists and check for a comparison failure:
for (int i=0; i < p1.size(); ++i) {
if (!p1.get(i).equals(p2.get(i))) {
System.out.println("peaks are not equal");
break;
}
}
This reduces an O(N^2) operation to one which is O(N*lgN), which is the penalty for doing both sorts (the final walk down the list is O(N), and would be negligible with either approach).
i have a situation where i have to read xml files where i get three elements like this
2019-03-19,null,null
2016-11-30,null,null
2016-10-14,null,null
2016-09-30,null,null
2016-09-30,1,YEARS
2016-09-30,3,MONTHS
2016-09-30,4,MONTHS
I have to store all three items on some data structure and apply my logic like below
I have to find the max of last item and then for that i have to find the max of second item then for that i have to find the max of first element of more than one is present .
Please suggest me some idea
Create a single object like below that can hold all three data elements and is also capable of handling a "null" value for the quantity and term length values. You may want to have the constructor convert the String date (2019-03-19) into a real date object or you could handle that before object creation. Then add these objects to a data structure (i.e. list, etc) that you can use to manage and organize them.
public class ListElement {
public Date date;
public Integer qty;
public String termLength;
public ListElement(Date d, Integer q, String t) {
this.date = d;
this.qty = q;
this.termLength = t
}
// getter methods
public Date getDate() {
return this.date;
}
public Integer getQty() {
return this.qty;
}
public String getTermLength() {
return this.termLength;
}
public toString() {
return System.out.println(this.date + "::" +
this.qty + "::" +
this.termLength)
}
}
You can create an enum if you have some predefined terms:
enum Term {
AGES, YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS;
}
And use it in your class with other two types as:
public class MyObjects {
private Date date;
private Integer quantity;
private Term term;
public MyObjects(Date date, Integer quantity, Term term) {
this.date = date;
this.quantity = quantity;
this.term = term;
}
// getters, setters
}
Then define the constructor that accepts these 3 arguments and use it while processing XML file.
Two different ways to store the data. One is 2D array and the other is arraylist. All the data is type String. You would have to Parse the Integers using Integer.parseInt() to get int value. You will also have to catch for null values. This assumes that your xml data have newline characters at the end of each line.
public static void main(String[] args) {
// TODO code application logic here
//Assuming there are \n char at end of line
String xml = "2019-03-19,null,null\n" +
"2016-11-30,null,null\n" +
"2016-10-14,null,null\n" +
"2016-09-30,null,null\n" +
"2016-09-30,1,YEARS\n" +
"2016-09-30,3,MONTHS\n" +
"2016-09-30,4,MONTHS";
System.out.println("2D Array Output:");
String[][] twoDArrayExample = twoDArrayVersion(xml);
//print 2D array
for(int i = 0; i < twoDArrayExample.length; i++)
{
for(int z = 0; z < twoDArrayExample[i].length; z++)
{
System.out.print(twoDArrayExample[i][z] + " - ");
}
System.out.println();
}
System.out.println("\n\nArray List Output:");
ArrayList<ArrayList<String>> arrayListExample = arrayListVersion(xml);
//print arraylist
for(ArrayList<String> entry : arrayListExample)
{
for(String item : entry)
{
System.out.print(item + " + ");
}
System.out.println();
}
}//end of main
static String[][] twoDArrayVersion(String xml)
{
String[][] dataHolder;
String[] tempDataHolder = xml.split("\n");
dataHolder = new String[tempDataHolder.length][3];
for(int i = 0; i < tempDataHolder.length; i++)
{
String[] tempDataHolder2 = tempDataHolder[i].split(",");
dataHolder[i][0] = tempDataHolder2[0];
dataHolder[i][1] = tempDataHolder2[1];
dataHolder[i][2] = tempDataHolder2[2];
}
return dataHolder;
}
static ArrayList<ArrayList<String>> arrayListVersion(String xml)
{
ArrayList<ArrayList<String>> dataHolder = new ArrayList();
String[] tempDataHolder = xml.split("\n");
for(int i = 0; i < tempDataHolder.length; i++)
{
ArrayList<String> tempArrayList = new ArrayList();
String[] tempDataHolder2 = tempDataHolder[i].split(",");
tempArrayList.add(tempDataHolder2[0]);
tempArrayList.add(tempDataHolder2[1]);
tempArrayList.add(tempDataHolder2[2]);
dataHolder.add(tempArrayList);
}
return dataHolder;
}
I want to create a program which displays current staff in the ArrayList before asking the user for input of a payroll number they'd like to remove. User then should input the payroll number of one of the three staff members and press enter. Upon pressing enter, the program should remove that particular staff member from the array list and display the entire list again (missing out the staff member they've deleted obviously). If the user no longer wishes to remove any payroll numbers, the payroll number entry should be 0 and should then display the contents of the list again.
The problem I'm having is with the remove part.
I've been recommended of two ways of achieving this:
This 'search' method should return either the position within the ArrayList (so that remove(<index>) may be used) or a reference to the object (so that remove(<objectRef>) may be used). If the staff member is not found, then the search method should return -1 (if remove(<index>) is being used) or null (if remove(<objectRef>) is being used).
However I am not sure how to implement this in Java.
Here is my file structure:
ArrayListTest.java
import java.util.*;
import personnelPackage.Personnel;
public class ArrayListTest
{
static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args)
{
long searchQuery;
ArrayList<Personnel> staffList = new ArrayList<Personnel>();
Personnel[] staff =
{new Personnel(123456,"Smith","John"),
new Personnel(234567,"Jones","Sally Ann"),
new Personnel(999999,"Black","James Paul")};
for (Personnel person:staff)
staffList.add(person);
do
{
showDisplay(staffList);
System.out.print("\nPlease enter a payroll number to search: ");
searchQuery = keyboard.nextLong();
searchForPayrollNumber(staffList, searchQuery);
}while(!(searchQuery == 0));
}
private static void showDisplay(ArrayList<Personnel> staffList)
{
System.out.print("\n------------- CURRENT STAFF LIST -------------\n");
for (Personnel person : staffList)
{
System.out.println("Payroll number: " + person.getPayNum());
System.out.println("Surname: " + person.getSurname());
System.out.println("First name(s): " + person.getFirstNames() + "\n");
}
}
public static void searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
{
long index = staffList.indexOf(searchQuery);;
for (Personnel person: staffList)
{
if (person.getPayNum() == searchQuery)
{
System.out.print("\n------------- Staff member found and removed! -------------");
System.out.println("\n\nFirst Name(s): " + person.getFirstNames());
System.out.println("\nSurname: " + person.getSurname());
System.out.print("\n-----------------------------------------------");
staffList.remove(index);
return;
}
}
System.out.print("\n------------- No staff members found. Program terminated -------------");
return;
}
}
Personnel.java (in its own package named personnelPackage)
package personnelPackage;
public class Personnel
{
private long payrollNum;
private String surname;
private String firstNames;
public Personnel(long payrollNum, String surname, String firstNames)
{
this.payrollNum = payrollNum;
this.surname = surname;
this.firstNames = firstNames;
}
public long getPayNum()
{
return payrollNum;
}
public String getSurname()
{
return surname;
}
public String getFirstNames()
{
return firstNames;
}
public void setSurname(String newName)
{
surname = newName;
}
}
Consider using Iterator for search and removal:
Iterator<Personnel> i = staffList.iterator();
while (i.hasNext()) {
Personnel p = i.next();
if (p.getPayNum() == searchQuery) {
// print message
i.remove();
return p;
}
}
return null;
If using List#remove() is strictly required, return found personnel p and call if (p != null) staffList.remove(p):
public static Personnel searchByPayNum(List<Personnel> ps, long num) {
for (Personnel p : ps) {
if (p.getPayNum() == num)
return p;
}
return null;
}
And in caller code:
Personnel p = searchByPayNum(staffList, query);
if (p != null) {
// log
staffList.remove(p);
}
public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery) {
//long index = staffList.indexOf(searchQuery);
for(int i = 0; i < staffList.size(); i++) {
if (staffList.get(i).getPayNum() == searchQuery) {
System.out.print("\n------------- Staff member found and removed! -------------");
System.out.println("\n\nFirst Name(s): " + staffList.get(i).getFirstNames());
System.out.println("\nSurname: " + staffList.get(i).getSurname());
System.out.print("\n-----------------------------------------------");
//staffList.remove(i);
return i;
}
}
System.out.print("\n------------- No staff members found. Program terminated -------------");
return -1;
}
Your search method shouldn't return void. It should return int or long instead,
public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
{
int index = -1;
for (int i = 0; i < staffList.size(); i++){
if(staffList.get(i).getPayNum() == searchQuery){
index = i;
System.out.print("\n------------- Found Staff member at position " + index + " in the list");
break;
}
}
if (index != -1){
staffList.remove(index);
System.out.print("\n------------- Removed the staff member");
}
return index;
}
Last approach returned the index. Now when you want to return the object:
public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
{
Personnel p = null;
for (int i = 0; i < staffList.size(); i++){
if(staffList.get(i).getPayNum() == searchQuery){
p = staffList.get(i);
break;
}
}
staffList.remove(p);
return p;
}
You must know that after removing it from the list, It will shift any subsequent elements to the left (subtracts one from their indices).
Also, just a suggestion:
Instead of
Personnel[] staff =
{new Personnel(123456,"Smith","John"),
new Personnel(234567,"Jones","Sally Ann"),
new Personnel(999999,"Black","James Paul")};
Why not
staffList.add(new Personnel(123456,"Smith","John"));
staffList.add(new Personnel(234567,"Jones","Sally Ann"));
staffList.add(new Personnel(999999,"Black","James Paul"));
This is just an advice. Since searching and removing are your primary goals, ArrayList is not the right collection to use.
Create a Hashmap with ID as key and Personnel object as value. This will help in identifying the Personnel in O(1) time and removal as well.
ArrayList should be used only when you know the index to read value. It then does that in O(1). If not, it is O(n) and not as efficient as HashMap.
I want to solve this problem without using arraylist.
i want to add the contact to its specific index in the array of strings. And then display all the added contacts in string format seperated by commas.
My code gives the result of only last added contract:
Contact [first=Bob, last=Moore, number=555-9756]
where is the problem in my code?
Is there any idea how to solve???
This class consist of the main method:
This is the main class:
public class ExampleApp {
public static void main(String[] args) {
PhoneBook pb = new PhoneBook("Personal book");
System.out.println( pb.getName() );
pb.add("Alice", "Green", "555-1234");
pb.add("Mary", "Smith", "555-6784");
pb.add("Bob", "Moore", "555-9756");
System.out.println( pb.toString() );// here i want to display all the contracts seperated by commas
System.out.println( pb.first() );// first contract
System.out.println( pb.get(2) );// second contract
String toBeFound = new String("Moore");
System.out.println( pb.find(toBeFound) );// display the found contract
}
}
This is the phonebook class:
public class PhoneBook {
public static final int MAX = 10;
public String name;
String[] contracts = new String[MAX]; // i created an array of strings
Contact c;
/**
* Create a new phonebook with given name
*/
public PhoneBook(String name) {
this.name = name;
}
/**
* Return the phonebook name
*/
public String getName() {
return name;
}
/**
* Insert a new contact at the end
*/
public void add(String first, String last, String number){
c=new Contact(first,last,number);
for(int i=0;i<MAX;i++){ // i added for each array index the contracts strings
contracts[i]= c.toString();
}
}
/**
* Return the first contact
*/
public String first() {
return get(1);
}
/**
* Return the i-th contact (supposing that first
* index is 1)
*/
public String get(int i) {
String s =contracts[i].toString();
return s;
}
/**
* Return a string containing the list of textual
* representation of all contacts, separated by ", ".
* List starts with "("and ends with ")"
*/
public String toString() {
String s= " ";
for(int i=1;i<MAX;i++){ // here i tried to display the string looping the array
s=contracts[i].toString();
}
return s;
}
/**
* Return the textual representation of first
* contact containing "needle"
*/
public String find(String needle) {
//TODO: to be implemented
return null;
}
}
This is the contact class :
public class Contact {
public String first;
public String last;
public String number;
public String[] contacts;
public Contact(String first, String last, String number) {
this.first=first;
this.last = last;
this.number=number;
}
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
#Override
public String toString() {
return "Contact [first=" + first + ", last=" + last + ", number="
+ number + "]";
}
}
You can use ArrayList for it. It will help you really much and you should make your veriables private.
private String first;
private String last;
private String number;
private ArrayList<String> list = new ArrayList<String>();
for(String pointer : list){
}
or you can make contact saver ArrayList
private ArrayList<Contact> list = new ArrayList<Contact>();
public Contact(String first, String last, String number) {
this.first=first;
this.last = last;
this.number=number;
}
public void add(String first, String last, String number){
c=new Contact(first,last,number);
list.add(c);
}
and you can access all veriables like that list.get(i).first.
You can save your contact class and contracts array in arraylist and it will give you more power to access. If you want to display your ArrayList, which index is not important, you need only ++i for it.
I changed your class look this:
public class PhoneBook {
public static final int MAX = 10;
public String name;
String[] contracts = new String[MAX]; // i created an array of strings
Contact c;
private int count = 0;// saved last index of array
public PhoneBook(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void add(String first, String last, String number) {
c = new Contact(first, last, number);
contracts[count] = c.toString(); // save your String inside of last index++
count++;
}
public String first() {
return get(1);
}
public String get(int i) {
String s = contracts[i].toString();
return s;
}
public String toString() {
for (int i = 0; i < MAX; i++) {
if (contracts[i] != null)
System.out.println(contracts[i].toString());
}
return "";
}
public String find(String needle) {
return null;
}
}
public class Contact {
public String first;
public String last;
public String number;
public Contact(String first, String last, String number) {
this.first = first;
this.last = last;
this.number = number;
}
#Override
public String toString() {
return "Contact [first=" + first + ", last=" + last + ", number="
+ number + "]";
}
}
//Personal book
//Contact [first=Alice, last=Green, number=555-1234]
//Contact[first=Mary, last=Smith, number=555-6784]
//Contact [first=Bob, last=Moore, number=555-9756]
you always delete your last toString method. Your Add method is wrong. You always turn 0 and write again inside of array.
You should keep track of the last contact added to your array :
private int lastIndex = 0; // index of first available index of the array
...
/**
* Insert a new contact at the end
*/
public void add(String first, String last, String number){
c=new Contact(first,last,number);
if (lastIndex < MAX)
contracts[lastIndex++]= c.toString();
}
Some other issues with your code :
/**
* Return the first contact
*/
public String first() {
return get(1); // should be get(0)
}
Calling toString() for contracts[i] is redundant, since it's already a String. Perhaps you meant to store Contact instances instead of Strings in your array? That would make more sense.
Add an extra variable static int Last = 0; To track how many contact you have added and update the add function as .
public void add(String first, String last, String number){
if(Last>=MAX){
System.out.println("Error in adding\n");
}
else{
c=new Contact(first,last,number);
contacts[Last] = c.toString();
Last++;
}
}
Change Tostring() for loop to last. So that you will be printing only added contact .In your case you are printing upto MAX that is wrong when less no of contacts are added.
You have to pass i=0,1,2,...,MAX-1 to get(i) function . Array is Zero(0) based indexed.
So, the problem you are having is that you always retrieve the last contact, regardless of which one you try to get. This is because when you add a new contact, you are actually replacing ALL the contacts, making them all the same. You are getting the correct contact from the phonebook, but they ALL have the same value.
To fix it, do the following:
public class PhoneBook
{
int contactsAdded = 0; // Add an integer to store how many contacts you have added
Contact[] contacts = new Contact[MAX]; //Change this to Contact array, not string
//Contact c; //You can remove this line
//Rest of your code
}
public void add(String first, String last, String number)
{
//Only add if the number of contacts is less than the max
if (contactsAdded < MAX)
{
//Construct the new contact when you use it.
contacts[contactsAdded] = new Contact(first, last, number);
contactsAdded++;
}
}
Not sure if I understood all of your code right, but I think you are overwriting all other contacts in your phone book:
public void add(String first, String last, String number){
c=new Contact(first,last,number); //(1)
for(int i=0;i<MAX;i++){ //(2)
contracts[i]= c.toString();
}
}
At position (1) a new Contact object is created and assigned to c. In the next step (2), you loop through the array and assign the info contained in c (the latest contact added) to all already entries in the contracts array.
Independent from your problem, I suggest that you replace the array of a fixed size with i.e. an ArrayList of type Contact. Adding entries to this list, iterating, sorting etc is very easy.