How to move position up by one when name is deleted - java

public void deleteQueue() {
int position;
PassengerQueue();
System.out.println("Enter Queue Position which you want to delete a customer from: ");
position = input.nextInt();
qitems[position] = "empty";
System.out.println("");
for (int look = front; look < end; look++) {
if (qitems[look].equals("empty")) {
System.out.println(look + ". " + qitems[look]);
} else {
System.out.println(look + ". " + qitems[look]);
}
}
What i am trying to do is, if a user enters a name, it will be put in position 0, if the user enters another name, it will put in posiiton 1 so 0 - bob, 1 - jon. what i want it to do is if bob position 0 gets deleted, it will change jons position from 1 to 0.

by using List there is no need to shift all the elements after delete, but if it's force to use array you can shift all in a simple loop:
public void deleteQueue() {
int position;
PassengerQueue();
System.out.println("Enter Queue Position which you want to delete a customer from: ");
position = input.nextInt();
System.out.println("");
for (int i = position; i < qitems.length-1; i++) {
qitems[i] = qitems[i+1];
}
qitems[qitems.length] = null;
}

When trying to figure out how to do an operation like this on a "low-level" object like a String array, you can always ask:
Is there a "higher-level" Java class that already exists that does the same thing?
In this case the answer is yes, there are a few... but I'm assuming you're not allowed to use them directly.
However, you can still look at their source code to see how they do exactly the same thing you're trying to do.
For example, in Android Studio, you can create a new ArrayList object... or just type "ArrayList," then right-click it... and select "go to Declaraction."
This will take you to the source code for the class you clicked on.
This is how the Android source code for ArrayList does a remove():
public E remove(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
You can see this is similar to Hamid's answer.

You can either loop through the array rearranging the positions or simply use some class that already does this for you, such as a linked list for example, which implements the remove(int index) method.

Put
qitems[position-1] = qitems[position]
inside of a for loop to cycle through each index that is after the one deleted.

Related

Adding an object to a sorted array into the correct spot

So I have this project and im writing the add method for my catalog class and this add method needs to add an item to a sorted array into the right place using insertion sort, unless the array has nothing in it in that case i just want to add it in normally. this whole project must use an array I cannot use an arraylist or anything else.
The problem I am having here is that the way my program currently is, its only adding one object to my array and each time i try to add a new one during run tine it jst replaces the item already in there. I know that my problem is something in the body of my while loop and the way i initialize my position variable.
here is the method im having trouble with.
public void addItem(Item theItem)
{
int position = size;
if(size != 0){
while (position > 0 && theItem.compareTo(items[position - 1]) < 0){
items[position] = items[position - 1];
position--;
}
items[position] = theItem;
}
else{
items[size] = theItem;
size++;
}
here is my compareTo method
public int compareTo(Item other){
if(this.getItemType().equals(other.getItemType())){
return this.itemnum - other.itemnum;
}
//item types are not equal
else
return this.getItemType().compareTo(other.getItemType());
//try writing code to compare by price as well
}
The most likely problem in your code is this line:
items[position-1] = items[position];
This will copy an item in you array from the current position to the position to the left of it.
When you insert a new item you want to copy items from the left to the current position to make room for the new item to the left.
Change it to
items[position] = items[position-1];
A size++ is also missing after the while block, inside the first if block.
I realized this when adding a second call to addItem in my test code below.
You could also put a single size++ statement outside of the if statement.
A Complete, Minimal, Reproducible Example that I used trying to fix it. I have used Integer instead of Item to avoid having to add more classes.
public class Main {
private int size = 0;
private Integer[] items = new Integer[20];
public static void main(String... args) {
new Main().execute(); // Moving us into a non-static context
}
public void execute() {
System.arraycopy(new Integer[] {1,2,3,4,6,7,8,9}, 0, items, 0, 8);
size = 8;
// items = [1,2,3,4,6,7,8,9,null,null,...]
addItem(5);
addItem(5); // test adding a second item
// items = [1,2,3,4,5,6,7,8,9,null,null,...]
for (Integer i : items) {
System.out.println(i);
}
}
public void addItem(Integer item) {
int position = size;
if (size != 0) {
while (position > 0 && item.compareTo(items[position - 1]) < 0) {
// items[position-1] = items[position]; // Result [1,2,3,4,5,null,null,...]
items[position] = items[position-1]; // Result [1,2,3,4,5,6,7,8,9,null,null,...]
position--;
}
items[position] = item;
size++; // this line was missing as well
} else {
items[size] = item;
size++;
}
// or a single size++; here, removing the other two
}
}
The ugly solution by making new array
public int[] addItem(int item, int[] items){
int[] tempArr = new int[items.length + 1];
boolean hasAlready = false;
for(int i = 0 ; i < items.length; i++){
if(hasAlready)tempArr[i + 1] = items[i];
else if(item < items[i]){
tempArr[i] = item;
tempArr[i + 1] = items[i];
hasAlready = true;
}else {
tempArr[i] = items[i];
}
}
//items = tempArr; if items is global variable
return tempArr;
}
One can use existing utility functions, Arrays.binarySearch, and System.arraycopy. Your loop was 1 off.
public void addItem(Item theItem) {
Comparator<Item> comparator = Comparator.comparing(Item::getItemType)
.thenComparingInt(it -> it.itemnum);
int position = Arrays.binarySearch(items, 0, size, theItem, comparator);
// If position >= 0 the item was found (maybe no need to insert?)
if (position < 0) {
position = ~position; // Insert position of not found item
}
System.arraycopy(items, position, items, position + 1, size - position);
items[position] = theItem;
size++;
}
Binary search results in the non-negative index when found, or the negative ~index when not found. Here binary search is done on a subarray from 0 upto size (excluded).
Same as Roger Gustavsson
public class Main {
private int size = 0;
private Integer[] items = new Integer[20];
public static void main(String... args) {
new Main().execute(); // Moving us into a non-static context
}
public void execute() {
System.arraycopy(new Integer[] {1,2,3,4,6,7,8,9}, 0, items, 0, 8);
size = 8;
// items = [1,2,3,4,6,7,8,9,null,null,...]
addItem(5);
// items = [1,2,3,4,5,6,7,8,9,null,null,...]
for (Integer i : items) {
System.out.println(i);
}
}
public void addItem(Integer item) {
if (size == 0) {
items[size] = item;
size++;
return;
}
int position = size;
while (position > 0 && item.compareTo(items[position - 1]) < 0) {
items[position] = items[position - 1];
position--;
}
items[position] = item;
size++;
}
}
on what you are trying to achieve, i think next solution will be starting point from where you can build your own solution depending your specific needs. i have Changed your main method a little bit, and i do not know if your classes implements comparable /Comparator or not.
public void addItem(Item theItem) {
int position = position(items, theItem); // position is a method that finds best position for inseriton
if (items[position] == null){ // if items at best position is null then add new element there
items[position] = theItem;
} else{
items[size] = theItem; // if not add element at last position
swapUp(size); // and swap them up to perfect position.
}
size++;
}
method that find best position looks like this.
private static int position(Item[] items, Item newItem) {
if (isEmpty(items))
return 0;
int pos=0;
int target=items.length-1;
while(pos < target){
int m = pos+(target-pos)/2;
if (items[m] !=null){
if(newItem.getNumber()>items[m].getNumber()){ // comparing depending on item number
pos=m+1;
}else{
target=m;
}
}else{
target = m;
}
}
return pos;
}
as you can see method is looking for position depending on item number, you can change this with your type, or do both type and number comparison. Swaping up is handled by thus 2 method.
private void swapUp(int lastPosition){
if (lastPosition == -1){
return;
}
Item lastItem = items[lastPosition];
Item p = items[lastPosition-1];
if (lastItem.getNumber() < p.getNumber())
replace(lastPosition, lastPosition-1);
else
lastPosition = 0;
swapUp(lastPosition-1);
}
private void replace(int from, int to){
Item temporary = items[from];
items[from] = items[to];
items[to] = temporary;
}
and again i'm doing comparison of numbers you can implement any kind of comparison you want. i saw your previous question and modeled your classes
Music{number=1111, name='White and Nerdy', price=2.5, pro='"Weird Al" Yankovic'}
Music{number=2222, name='Amish Paradise', price=2.22, pro='"Weird Al" Yankovic'}
Music{number=3333, name='The Saga Begins', price=2.0, pro='"Weird Al" Yankovic'}
Movie{number=4444, name='UHF', price=9.99, pro='"Weird Al" Yankovic'}
Movie{number=5555, name='The Dark Crystal', price=8.99, pro='"Jim Henson'}
Movie{number=6666, name='Die Hard', price=13.99, pro='Bruce Willis'}
Movie{number=6969, name='The Adventures of Mr. Winky', price=9.99, pro='Richard Dickinson'}
Book{number=7777, name='When I Grow Up', price=7.98, pro='"Weird Al" Yankovic'}
Book{number=8888, name='The Chronicles of Pern: First Fall', price=5.99, pro='"Anne McCaffrey'}
Book{number=9999, name='Get gud you scrub', price=2.5, pro='Steve "Troll" Rathier'}
as you can see they are in sorted order.

Expanding queue overwrites all previous entries with new entry

I have written a queuing program that allows the user to enter student objects into a queue. Here is my section of the code that I'm having trouble with:
private void resize(int max) {
assert max >= numOfNodes;
StudentListing[] temp = (StudentListing[]) new Object[max];
for (int i = 0; i < numOfNodes; i++) {
temp[i] = data[(front + i) % data.length];
}
data = temp;
front = 0;
rear = numOfNodes;
}
public void enqueue(StudentListing newNode) {
if (numOfNodes == data.length) {
resize(data.length * 2);
}
data[rear++] = newNode;
if (rear == data.length) {
rear = 0;
}
numOfNodes++;
}
The problem I am having is that when I go to add a new student into the queue and it is full, it carries out the resize method and overwrites all of my previous entries with the new student entry.
For example: a student named John gets added to the queue with a maximum size of 1. The user goes to add another student named Tom to the queue; it expands the queue, but then overwrites John. The end result is that there are two Toms in the queue instead of one John and one Tom.
I need help figuring out how to stop it from overwriting and instead add all previous entries to the newly created expanded queue, and then add the new entry to the end of said queue. Thank you in advance :)

remove(int index) LinkedList Self-Implementation

I am trying to learn performance of LinkedList in comparison to ArrayList
I have made my removal method as follows
Data In the LinkedList, which is being removed is about 1million elements.
My Problem, After Removing All Items: This is the Time Recd.
If I Use Java LinkedList remove(int index) Time: 2000 nanoseconds
If I Use my Custom remove(int index) Time: 34407000 nanoseconds
Could someone please look at my code and tell me where I am going wrong. I am actually suppose to remove the data by index positions, since the comparison I am trying to attain are by index positions for ArrayList.
public Object remove(int index)
{
checkElementIndex(index);
return unlink(getNode(index));
}
private Object unlink(ListNode node)
{
final Object element = node.item;
final ListNode next = node.next;
final ListNode prev = node.prev;
if (prev == null)
{
first = next;
} else
{
prev.next = next;
node.prev = null;
}
if (next == null)
{
last = prev;
} else
{
next.prev = prev;
node.next = null;
}
node.item = null;
size--;
return element;
}
private ListNode getNode(int index)
{
if (index < (size >> 1))
{
ListNode node = first;
for (int i = 0; i < index; i++)
{
node = node.next;
}
return node;
} else
{
ListNode node = last;
for (int i = size - 1; i > index; i--)
{
node = node.prev;
}
return node;
}
}
private void checkElementIndex(int index)
{
if (index < 0 || index >= size)
{
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
// BOTH THE LIST CONTAIN 1million items.
startTime = System.nanoTime();
for (int i = linkedList.size()-1; i >= 0; i--)
{
linkedList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedList Removal Time: " + duration);
// This is the Java Collection LinkedList
startTime = System.nanoTime();
for (int i = linkedList.size()-1; i >= 0; i--)
{
javaLinkedList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("My Removal Time: " + duration);
I appreciate, each and every possible suggestion. Thank you.
(continued from comments)
No problem! First step is to download a profiler (I use VisualVM. There are other ones out there, but unfortunately I'm not familiar with them...) Once that's downloaded, go ahead fire that up.
The next step is figuring out how to attach the profiler to your process. Once you start up VisualVM, you should see a list of running Java programs on the right. You can ignore that for now. The trick is that you'll need a long-running program to have enough time to attach the profiler to the process. For something like your code, an easier way would be to use Scanner.nextLine() to block the program in between loops, sort of like this:
Scanner scanner = new Scanner(System.in);
scanner.nextLine(); // This stops the program and waits for user input.
// This will give us all the time in the world to attach the profiler.
// Your code
for (int i = linkedList.size()-1; i >= 0; i--)
{
linkedList.remove(i);
}
scanner.nextLine(); // Same thing here
for (int i = linkedList.size()-1; i >= 0; i--)
{
javaLinkedList.remove(i);
}
Now, go ahead start your program. If you go back to VisualVM, you should be able to see your program!
Now double-click on your program. You should see a few messages appear in the console in your program, and the view in VisualVM should change. Go to the "Sampler" tab, click "CPU", then go back to your program and hit enter.
What you see should be pretty self-explanatory. On the left are fully qualified method names with package + class, and a bar representing the portion of CPU time that methods use. Use that to identify where your program is spending all its time. And there you go! If you need more time to profile, just add more elements to the linked lists.
Just a word of caution though; profiling can be deceiving, because if another method is messing up your linked list structure it can make a perfectly good method work far harder than it has to. For example, I had to implement HashMap as part of a school assignment. When I profiled I noticed that the code to look in buckets was taking up 97%+ of CPU time, even though there was nothing wrong with it. Turns out that a test to get a proper bucket had >> instead of <<, turning the HashMap into a LinkedList instead! So while profiling is a good start (and usually is the only thing you need to do to identify problems), just keep in mind that the errors could be elsewhere.
I hope that this helped!

Finding information stored in array by binary search

This is a small library with two books for the sake of the question, it allows the user to type in a random number, and if that number matches up with a book the title of the book is outputted. I've created a class called 'Book' which houses all the titles.
String book1, book2;
class Book {
Book (int _input, String book_1, String book_2) {
book1 = book_1 = "Read This Book";
book2 = book_2 = "How to Read a Book";
I apologize if my code is all one big mess that makes no sense...
}
}
ArrayList <Book> titles = new ArrayList <Book>(50);
public static Boolean binarySearch(String [] A, int left, int right, String V) { //binary search
int middle;
Boolean found = false;
while (found == false && left <= right) {
//If middle item == 0, returns true
middle = (left + right)/2;
int compare = A[middle].compareTo(V);
if (compare == 0) {
found = true;
} else {
if (compare >0) {
right = middle -1;
} else {
left = middle + 1;
}
}
}
if (left > right) {
return false;
} else {
return true;
}
}
Then the problem...I'm not sure how to use the binary search to actually output any information after pressing the "find" button, any ideas on what I should below to make this work?
private void findButtonActionPerformed(java.awt.event.ActionEvent evt) {
//Take inputted values which will match with book title
int input = Integer.parseInt(enterNumberField.getText());
//Store values in array
Book c = new Book (input, book1, book2);
titles.add(c);
String temp;
//calls out information in array
for (int j=0; j<=input; j++) {
for (int x=0; x<=input; x++) {
temp = titles.get(x) + "\n";
}
binarySearchField.setText("" + j); //should output book title
}
You want your binary search to return not just a true or false. You want it to return Book, the item it found, or null if it found no book matching this query. To be consistent you probably want to change the name from binarySearch, to getBook, or some other better suited name. In your case you don't want to know if an element is there, you want to get the element for use later (printing).
This is how collections are expected to behave when you query them. Just check out the get methods from any of the Java collections and you will see they do the same, returning the item if it's there, or null.
Here is some example code. This is just example code! So modify as you like, and also be careful about bugs, I used your search which I'm going to assume is correct to start with. Also know that there are better many good ways of storing a key to a value, Map for example, that I'm not going to use here.
public class Book{
public String title;
public int sameTitle(String bookTitle) {
return this.title.compareTo(bookTitle);
}
}
public static Book getBook(Book [] A, int left, int right, String bookTitle) { //binary search
int middle;
while (left <= right) {
//If middle item == 0, returns true
middle = (left + right)/2;
int compare = A[middle].sameTitle(bookTitle);
if (compare == 0) {
return A[middle];
} else {
if (compare >0) {
right = middle -1;
} else {
left = middle + 1;
}
}
}
return null;
}
// example use of getting and using the book
Book b = getBook(...);
if (b != null){
System.out.println("Success! you found the book " + b);
}
Try to change this line:
int compare = A[middle].compareTo(V);
if (compare == 0) {
found = true;
To:
int compare = A[middle].compareTo(V);
if (compare == 0) {
return A[middle];
And be sure to get the result in your findButtonActionPerformed method.
Also, it appears to be a mistake in your code... Should not A be a book array instead of a string array?

Iterate over HashMap and get "Lowest" Integer of the value in the Object

for (Entry<String, Data> entry : list.entrySet()) {
if(entry.getValue().getRoom() == 1){
if(entry.getValue().getName().equalsIgnoreCase("RED")){
entry.getValue().getPosition() // need to get the lowest free number
// between the range of 1-6
}
}
}
How to get the lowest free spot of the getPosition in this situation. getPosition values are between 1-6 and there are only one of each value Room = 1 and Name = RED.
For example if 1,3,4,6 exists in getPosition(with room=1 and name=red) then the output should be 2. That is the lowest number that is free in getPosition in the specific combination. Hope u can help me out.
Well, it sounds like the simplest approach would be something like:
boolean[] taken = new boolean[7]; //(0-6 inclusive)
// You were never using the key as far as I could see...
for (Data data : list.values()) {
if (data.getRoom() == 1 && data.getName().equalsIgnoreCase("RED")) {
taken[data.getPosition()] = true;
}
}
for (int i = 1; i <= 6; i++) {
if (!taken[i]) {
return i;
}
}
// Do whatever you want if there are no free positions...

Categories