I was trying to take in a user ID and check for it against a list to see if it exists already. If it does, then print "ID already exists" if not, then take in the user name and store it in the list.
private LinkedList<Person> people = new LinkedList<Person>();
private void addPerson(){
int personId = readPersonId();
Person person = person(personId);
if (person.hasId){
System.out.println("ID already exists");
}
else{
String s = readName();
people.add(new Person(personId, s, 2));
}
}
However my program stops in the first loop for some reason.
You can dump your arraylist into a set and than compare these 2. If the size of the set is lower than arraylist size, then there are duplicates.
ArrayList<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);
if(set.size() < list.size()){
/* There are duplicates in your arrayList */
}
go through the list of people you have already and look for anyone with the same id. if there are no matching ones, the go a head and add the new person to the list.
private LinkedList<Person> people = new LinkedList<Person>();
private void addPerson(){
int personId = readPersonId();
boolean found = false;
for (Person curr : people) {
if (curr.getId() == personId){
System.out.println("ID already exists");
found = true;
break;
}
}
if (!found) {
Person person = person(personId);
String s = readName();
people.add(person);
}
}
Related
I'm given the task of adding a value into an ArrayList alphabetically (by lastname first, and firstname if lastnames are the same),I'm not allowed to sort the ArrayList once all the inputs are given. What I am suppose to do is determine the location of where the value should be each time an input is given and place it there. Example values: Inputs are {John Doe, Bryan Sully, Harry Ache, Ali Doe, Bry Dyre} , Output should be {Harry Ache, Ali Doe, John Doe, Bry Dyre, Bryan Sully}. However, in cases where there are two of the same last names, what will occur is {Harry Ache, Ali Doe, Bry Dyre, John Doe, Bryan Sully}, why?
ArrayList<Person> list = new ArrayList<Person>();
public void addPerson(Person p){
if(list.size() == 0){
list.add(p);
} else{
for(Person pp: list){
int getIndex = list.indexOf(pp);
int lOrder = p.getLastName().compareTo(pp.getLastName());
if(lOrder > 0){
list.add(getIndex + 1, p);
break;
} else if(lOrder == 0){
int fOrder = p.getFirstName().compareTo(pp.getFirstName());
if(fOrder > 0){
list.add(getIndex, p);
break;
} else {
list.add(getIndex + 1, p);
break;
}
} else {
list.add(getIndex, p);
break;
}
}
}
}
One issue with your code is that you are making an insertion after a single iteration of your loop, inserting Person p only in comparison to the first Person in the list.
Here is an improved implementation:
public void addPerson(Person person) {
if (list.isEmpty()) {
list.add(p);
} else {
// the position where you will insert the Person;
// default value is list.size(), so it can be added to the end
int position = list.size();
Person p;
for (int i = 0; i < list.size(); i++) {
p = list.get(i);
// if the comparison result is > 0, you found the first Person
// in the list that comes alphabetically after;
// Insert person before it, at position i
if (compare(p, person) > 0) {
position = i;
break; // only break now that you've found the insert position
}
}
list.add(person, position);
}
}
/**
* #return 0 if both Persons p1 & p2 have the same names,
* a positive number if p1 is lexicographically greater than p2,
* or a negative number if p1 is lexicographically less than p2
*/
private int compare(Person p1, Person p2) {
int result = p1.getLastName().compareTo(p2.getLastName());
if (result == 0) {
result = p1.getFirstName().compareTo(p2.getFirstName());
}
return result;
}
As others suggested, implementing the Comparable interface in Person if possible can also help create a cleaner implementation.
Few improvements.
You are better off if you can iterate the list using the index like
for(int i = 0; i < array.size(); i++)
You need not have to check for lastName and firstName separately. You can just compare both of them together (p.lastName + p.firstName).compareTo(pp.lastName + pp.firstName) and act upon the result. As you already have the index of the current element, you just have to check if you just insert the new item on the same index or not.
Here is a sample implementation
static void addPerson(Person person) {
for (int i = 0; i < sortedList.size(); i++) {
var existingPerson = sortedList.get(i);
var compareResult = compare(existingPerson, person);
if (compareResult > 0) {
sortedList.add(i, person);
return;
}
}
sortedList.add(person);
}
static int compare(Person p1, Person p2) {
return (p1.lastName + p1.firstName).compareTo(p2.lastName + p2.firstName);
}
The problem with your algorithm, is that you always looking at the first person in the target list, and making decisions solely on that person, notice how all your "branches" have a break statement at the end?
I understand your "reason" for adding all those break statements, those make sure the new person always gets inserted into the list, when it doesn't match, the same reason why your first check if the list is empty.
To properly implement an "insertion sort" system, you actually need to loop over all the indexes of your list.
An simple "insertion sort" algorithm looks like this:
Loop over the target list
Check if existing entry is "bigger" than the newly person
If the existing entry is bigger, we need to move that entry (all all remaining entries) up 1 spot, insert out entry, and abort
If we are done looping, and we didn't abort in the above steps, insert our entry at the end of the list.
ArrayList<Person> list = new ArrayList<Person>();
public void addPerson(Person p){
// Loop
int size = list.size();
for(int getIndex = 0; getIndex < size; getIndex++){
Person pp = list.get(getIndex);
// Compare
int compare = p.getLastName().compareTo(pp.getLastName());
if (compare > 0) {
continue;
} else if(compare == 0) {
if (p.getFirstName().compareTo(pp.getFirstName()) > 0) {
continue;
}
}
// Add in existing slot
list.add(getIndex, p);
return;
}
// Add at the end
list.add(p);
}
One hard part of this, is the fact that we have to compare on 2 things for a single person, this makes the compare logic way harder than it needs to be. This can be solved by factoring this part out to a "helper" comparator that does this logic merging for us:
Comparator<Person> compare = Comparator
.comparing(Person::getLastName)
.thenComparing(Person::getFirstName);
// Then, inside the above loop:
...
// Compare
if (compare.compare(p, pp) > 0) {
continue;
}
...
I have simply this below class structure and I want to add any item to it.
public class Person implements Serializable {
private String name;
private String mobile;
public Person(String n, String e) { name = n; mobile = e; }
public String getName() { return name; }
public String getMobile() { return mobile; }
#Override
public String toString() { return name; }
}
I want to add any item like with this:
people = new Person[]{
new Person("Hi" , " programmer"),
new Person("Hello", " world")
};
My code is this and I want to add items into that by while() my code is don't correct.
people = new Person[]{};
while (phones.moveToNext())
{
people = new Person("Hi" , " programmer");
people = new Person("Hello", " world")
}
you have error in your source code you are trying to put Object of person into array so it will gives you compilation error
to overcome this problem first take List of Type Person and convert it into array and do your business logic on Array its better to use List instead of Array
List<Person> personlst = new ArrayList<Person>();
while (phones.moveToNext())
{
personlst.add(new Person("Hi" , " programmer"));
personlst.add(new Person("Hello", " world"));
}
Object[]arryPer = personlst.toArray();
Person[]people = new Person[arryPer.length];
for (int j = 0; j < arryPer.length; j++) {
people[j] = (Person) arryPer[j];
}
above code of block give you array of type people
You are not defining the number of elements that you want to push into array. Also you are not even making those elements to an array. You should do something like:
int i =0;
people = new Person[1000];// you need to define how many elements you need here or go for list
while (phones.moveToNext())
{
people[i++] = new Person("Hi" , " programmer");
people[i++] = new Person("Hello", " world")
}
Define first the size of your Person.
Person[] people = new Person[10];
then do your iteration for example.
for(int i = 0; i < 0; i++){
people[i] = new Person("Hi" , " programmer");
}
first put all elements in list then form the array:
List<Person> list = new ArrayList<Person>();
while (phones.moveToNext()) {
list.add(new Person("Hi", " programmer"));
list.add(new Person("Hello", " world"));
}
Person[] persons = new Person[list.size()];
list.toArray(persons);
}
Try Arrays.asList
http://www.tutorialspoint.com/java/util/arrays_aslist.html
Note - it is good only for a small number of elements as arrays generally take contiguous memory.
As people have stated above, list is any day better from space point of view.
Implementing a Linked List, store up to 10 names, ordered in first in First Out. Then implement two methods, one of which to sort it alphabetically by last names. This is where I am having some trouble. Here is what I tried:
Recursion. The method calls two nodes, compare them, swap if needed and then calls itself. Doesn't work with odd number of names and tends to be full bugs.
Collection but I don't know enough about it to use it effectively.
Sorting algorithms (ex. bubble sort): I can go though the list but have a hard time getting the nodes to swap.
My question is: What is the easiest way to do this?
public class List
{
public class Link
{
public String firstName;
public String middleName;
public String lastName;
public Link next = null;
Link(String f, String m, String l)
{
firstName = f;
middleName = m;
lastName = l;
}
}
private Link first_;
private Link last_;
List()
{
first_ = null;
last_ = null;
}
public boolean isEmpty()
{
return first_ == null;
}
public void insertFront(String f, String m, String l)
{
Link name = new Link(f, m, l);
if (first_ == null)
{
first_ = name;
last_ = name;
}
else
{
last_.next = name;
last_ = last_.next;
}
}
public String removeFront()
{
String f = first_.firstName;
String m = first_.middleName;
String l = first_.lastName;
first_ = first_.next;
return f + " " + m + " " + l;
}
public String findMiddle(String f, String l)
{
Link current = first_;
while (current != null && current.firstName.compareTo(f) != 0 && current.lastName.compareTo(l) != 0)
{
current = current.next;
}
if (current == null)
{
return "Not in list";
}
return "That person's middle name is " + current.middleName;
}
}
public class NamesOfFriends
{
public static void main(String[] args)
{
List listOfnames = new List();
Scanner in = new Scanner(System.in);
for(int i = 0; i < 3; i++)
{
if(i == 0)
{
System.out.println("Please enter the first, middle and last name?");
listOfnames.insertFront(in.next(), in.next(),in.next());
}
else
{
System.out.println("Please enter the next first, middle and last name");
listOfnames.insertFront(in.next(), in.next(),in.next());
}
}
System.out.println("To find the middle name, please enter the first and last name of the person.");
System.out.println(listOfnames.findMiddle(in.next(),in.next()));
}
}
Edit
After working on it a bit, I figured out how to go about sorting it. For that purpose, I am trying to implement a remove method that can remove a node anywhere on the list. While it does compile, it doesn't do anything when I run the program.
public Link remove(String lastName)
{
Link current_ = first_;
Link prior_ = null;
Link temp_ = null;
while (current_ != null && current_.lastName.compareTo(lastName) != 0)
{
prior_ = current_;
current_ = current_.next;
}
if (current_ != null)
{
if (current_ == last_)
{
temp_ = last_;
last_ = prior_;
}
else if (prior_ == null)
{
temp_ = first_;
first_ = first_.next;
}
}
else
{
temp_ = current_;
prior_.next = current_.next;
}
return temp_;
}
2: Collections is the easiest, but it seems to be not allowed in your homework
3: BubbleSort is easy but the worst known sorting algo, however for your homework it probably is ok
1: This is the same as bubble sort, but is prefered to be done without recursion
In BubbleSort you loop through your elements again and again till no swaps are neeeded anymore, then you are ready.
Collection is the easiest way to accomplish this.
Implement Comparable
Override hashcode and equals
Collection.sort()
You already has the linked list implemented, that is good.
Have you considered implementing MergeSort as the sorting algorithm? Being the divide&conquer algorithm, you will always end up with only two elements to form a list with.
The merge part is going to be trickier, but also easy. Basically you just create a new list and start filling it up with elements you get by comparing the first values of the two merging sets.
So for instance if you have two sets to merge:
[A]->[C]->[D]
[B]->[E]->[F]
the mergin process will go:
[A]
[C]->[D]
[B]->[E]->[F]
[A]->[B]
[C]->[D]
[E]->[F]
[A]->[B]->[C]
[D]
[E]->[F]
[A]->[B]->[C]->[D]
[E]->[F]
[A]->[B]->[C]->[D]->[E]
[F]
[A]->[B]->[C]->[D]->[E]->[F]
Ran into a little problem and I'm not entirely sure why this code won't work.
I have a 2d arraylist:
List<List<String>> matrix = new ArrayList<List<String>>();
I have a button that adds an arraylist to the matrix based on user input. But before user input is added, I need the button to search for if that string already exists.
The code I have doesn't produce any errors, but it doesn't seam to discriminate between existing and none existing strings except for the very first element. It adds everything the user puts in regardless of it's existence. Also the code will only function if the matrix array already has some elements in it, if the matrix is empty, the code won't work at all. What am I doing wrong?
String name = NameTXT.getText();
String amount = CountTXT.getText();
for (int i = 0; i < matrix.size(); i ++){
String search = matrix.get(i).get(0);
if (name.equals(search)){
OutputTXT.setText("Item already exists");
break;
} else {
List<String> col = new ArrayList<String>();
col.add(name);
col.add(amount);
matrix.add(col);
OutputTXT.setText(amount +" "+ name +" added");
break;
}
}
break; means that you completely stop the for loop. You can use continue if you just want to go to the next item in the matrix.
separate searching for item and item insertion:
String name = NameTXT.getText();
String amount = CountTXT.getText();
// searching for product
boolean isNewItem = true;
for (int i = 0; i < matrix.size(); i++){
String search = matrix.get(i).get(0);
if (name.equals(search)){
OutputTXT.setText("Item already exists");
isNewItem = false;
break;
}
}
// insert if new item
if ( isNewItem ) {
List<String> col = new ArrayList<String>();
col.add(name);
col.add(amount);
matrix.add(col);
OutputTXT.setText(amount +" "+ name +" added");
}
actually, it would be better to design in abstract way and use the language tools to solve your problem, for example the list would be easier to work if its List of item:
class Item {
private String name;
private String amount;
public Item(String name, String amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return this.name;
}
public String getAmount() {
return this.amount;
}
#Override
public boolean equals(Object other) {
if ( other == this )
return true;
if ( other == null )
return false;
if ( other.getClass() != this.getClass() )
return false;
Item otherItem = (Item) other;
return otherItem.getName().equals(this.name);
}
}
then the list would be:
List<Item> items = new ArrayList<Item>();
when you need to search:
Item item = new Item(NameTXT.getText(), CountTXT.getText());
if ( !items.contains(item) ) {
items.add(item);
}
Uhhh... i would try foreach syntax instead of a classical for if i were you. I guess that's why your code does not work when the matrix is empty : you cant't do this with an empty arraylist :
matrix.get(i).get(0);
Also , the else clause is embedded inside the if clause , so i'm not sure how the code compiles.
You should try something like :
for(List<String> elem : matrix){
if(elem.get(0).equals(name)){
// do stuff
}
else{ //do other stuff }
}
Why loop over every item in the list and not just use contains:
for(List<String> list : matrix){
if(!list.contains(name){
//add element to matrix
}
}
I ran into a bind whereby I had to sort the data read from the phones PIM. In doing this I lost the other to which each contact field was referenced to the telephone number because I made use of 2 separate vectors as illustrated below
Before sorting
Nna - +445535533
Ex - +373773737
Ab - +234575757
After sorting.(Which shouldn't be)
Ab - +445535533
Ex - +373773737
Nna - +234575757
This gives an undesired behavior since the sort removes the index to index pointer of the vectors and a selected name (in a Multiple list Box) will get a wrong number.
Alternatively,
I used a hashtable, with the intention of using the names as keys and numbers as the values.
But this pairing means duplicate names being used as keys will not be allowed. Thus I made it a i.e the phone number as keys instead.
I don't want to sound like a cry baby so I stop here for a while and so you the code with a hope u guys would understand it
MY QUESTION
1. Is there a better way/algorithm to implement this?
2. How do I implement the getSelectedItems() in such a ways that it grabs the numbers of the selected indexes of a MULTIPLE CHOICE LIST from a hashTable
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import javax.microedition.lcdui.List;
import javax.microedition.pim.Contact;
import javax.microedition.pim.ContactList;
import javax.microedition.pim.PIM;
import javax.microedition.pim.PIMException;
/**
*
* #author nnanna
*/
public class LoadContacts implements Operation {
private boolean available;
private Vector telNames = new Vector();
Vector telNumbers = new Vector();
Hashtable Listcontact = new Hashtable();
private String[] names;
public Vector getTelNames() {
return telNames;
}
public Hashtable getListcontact() {
return Listcontact;
}
public void execute() {
try {
// go through all the lists
String[] allContactLists = PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
if (allContactLists.length != 0) {
for (int i = 0; i < allContactLists.length; i++) {
System.out.println(allContactLists[i]);
System.out.println(allContactLists.length);
loadNames(allContactLists[i]);
System.out.println("Execute()");
}
} else {
available = false;
}
} catch (PIMException e) {
available = false;
} catch (SecurityException e) {
available = false;
}
}
private void loadNames(String name) throws PIMException, SecurityException {
ContactList contactList = null;
try {
contactList = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY, name);
// First check that the fields we are interested in are supported(MODULARIZE)
if (contactList.isSupportedField(Contact.FORMATTED_NAME) && contactList.isSupportedField(Contact.TEL)) {
Enumeration items = contactList.items();
Hashtable temp = new Hashtable();
while (items.hasMoreElements()) {
Contact contact = (Contact) items.nextElement();
int telCount = contact.countValues(Contact.TEL);
int nameCount = contact.countValues(Contact.FORMATTED_NAME);
if (telCount > 0 && nameCount > 0) {
String contactName = contact.getString(Contact.FORMATTED_NAME, 0);
// go through all the phone availableContacts
for (int i = 0; i < telCount; i++) {
System.out.println("Read Telno");
int telAttributes = contact.getAttributes(Contact.TEL, i);
String telNumber = contact.getString(Contact.TEL, i);
Listcontact.put(telNumber, contactName);
temp.put(contactName, telNumber);
}
names = getSortedList();
// Listcontact = temp;
System.out.println(temp + "-------");
System.out.println(Listcontact + "*******");
shortenName(contactName, 20);
}
available = true;
}
} else {
available = false;
}
} finally {
// always close it
if (contactList != null) {
contactList.close();
}
}
}
private void shortenName(String name, int length) {
if (name.length() > length) {
name = name.substring(0, 17) + "...";
}
}
public Vector getSelectedItems(List lbx) {
boolean[] arrSel = new boolean[lbx.size()];
Vector selectedNumbers = new Vector();
int selected = lbx.getSelectedFlags(arrSel);
String selectedString;
String result = "";
for (int i = 0; i < arrSel.length; i++) {
if (arrSel[i]) {
selectedString = lbx.getString(lbx.getSelectedFlags(arrSel));
result = result + " " + i;
System.out.println(Listcontact.get(selectedString));
// System.out.println(telNumbers.elementAt(i));
}
}
return selectedNumbers;
}
private String[] sortResults(String data[]) {
RecordSorter sorter = new RecordSorter();
boolean changed = true;
while (changed) {
changed = false;
for (int j = 0; j < (data.length - 1); j++) {
String a = data[j], b = data[j + 1];
if (a != null && b != null) {
int order = sorter.compare(a.getBytes(), b.getBytes());
if (order == RecordSorter.FOLLOWS) {
changed = true;
data[j] = b;
data[j + 1] = a;
}
}
}
}
return data;
}
public String[] getNames() {
return names;
}
Vector elements = new Vector();
private String[] getValueArray(Hashtable value) {
System.out.println(Listcontact + " c");
Enumeration e = value.elements();
while (e.hasMoreElements()) {
elements.addElement(e.nextElement());
}
String[] elementsArray = new String[elements.size()];
elements.copyInto(elementsArray);
elements.removeAllElements();
System.out.println(elementsArray + " k");
return elementsArray;
}
public void getDuplicates(Vector realValue) {
Vector duplicate = new Vector();
Enumeration e = realValue.elements();
for (int i = 0; e.hasMoreElements(); i++) {
if (duplicate.isEmpty() || !duplicate.elementAt(i).equals(e.nextElement())) {
break;
} else {
duplicate.addElement(e.nextElement());
}
}
}
public String[] getSortedList() {
return sortResults(getValueArray(Listcontact));
}
}
Let me reiterate you requirement: You want a method that will sort the contacts read from native phonebook, then alphabetically sort them on name.
Following is the approach,
Replace the vectors and hash-tables in your code with a single vector, say contactListVector, containing elements of type ContactItem, don't worry this class is explained below. Fundamentally the contact's name and number(s) are linked together in a ContactItem, hence you do not have to worry about there mappings which reduces the usage of redundant data structures.
class ContactItem {
private String name;
private String tnumber; //this can also be a data structure
//for storing multiple numbers
ContactItem( String name, String tnumber) {
this.name = name;
this.tnumber = tnumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTnumber() {
return tnumber;
}
public void setTnumber(String tnumber) {
this.tnumber = tnumber;
}
}
You can reuse the sorting algorithm on contactListVector by comparing the member variable ContactItem.name of the vector element. Also you can deploy different sorts on member variables numbers and/or names. Also there are lots of libraries for JavaME available that have better sorting algorithm's implemented if need be use them.
I would recommend you to perform the sorting once on the contactListVector elements at the end of your method loadNames(...) maybe in the finally block triggered by some boolean variable. The current sorting call in each iteration on items enumeration is expensive and time consuming.
Also you can serialize / deserialize the ContactItem thus persist your contact list.
Let me know if you need detailed explanation.
What about inserting the contact name and numbers inside a recordStore , so you can later make a sort by creating a class which implements RecordComparator.
This statement in your code makes no sense:
selectedString = lbx.getString(lbx.getSelectedFlags(arrSel))
Per lcdui List API documentation above will return the string located at the index equal to the number of selected elements why would you need that?
If you need to output selected text for debugging purposes, use lbx.getString(i) instead.
To implement the getSelectedItems() in such a ways that it grabs the numbers of the selected indexes of a MULTIPLE CHOICE LIST do about as follows:
public Vector getSelectedItems(List lbx) {
boolean[] arrSel = new boolean[lbx.size()];
Vector selectedNumbers = new Vector();
int selected = lbx.getSelectedFlags(arrSel);
System.out.println("selected: [" + selected + "] elements in list");
String selectedString;
String result = "";
for (int i = 0; i < arrSel.length; i++) {
if (arrSel[i]) {
// here, i is the selected index
selectedNumbers.addElement(new Integer(i)); // add i to result
String selectedString = lbx.getString(i);
System.out.println("selected [" + selectedString
+ "] text at index: [" + i + "]");
}
}
return selectedNumbers;
}
As for sorting needs, just drop the HashTable and use Vector of properly designed objects instead as suggested in another answer - with your own sorting algorithm or one from some 3rd party J2ME library.
I would suggest you to have Contact class with name and Vector of numbers. And instead of sorting names array sort the array of contacts.