Let's say I'm running a book store and someone placed an order for a list of books. B,C,D,A,A,A (the parameter)
I need to return true if all of those books are found in my inventory array. If there are two instances of the same book in the list being passed in (in this case A), I need to check to see if there are that many instances of that book in my inventory. I'm traversing through both the parameter array and the inventory array but as of now my code is returning true even if there's only one A book in my inventory. I am stuck on the logic of writing code that checks to see that there are 3 A books in my inventory. In essence, the customer is placing an order and I need to tell them if I have the books he wants. The order list will be arranged in descending order of retail value. So all three A books will be right next to each other if that makes it easier.
Here is the skeleton of what I have so far.
public boolean checkAvailability(customersOrder listToCheck) {
for(int i = 0; i<listToCheck.items.length; i++){ //listToCheck's items array
for(int j = 0; j<items.length; j++){ //inventory array
if(listToCheck.items[i].equals(items[j])){
return true;
}
}
}
return false;
}
This is very dependent on how you are storing your data, the simplest and most generic way that will work with virtually all data designs though is:
Sort your array before processing it, this will group all identical books together.
Now when you look to see whether you have enough books you can check there are enough to cover every instance of that book within the order.
As this looks like homework (too simple restrictive datastructures), just an idea
Walk the listToCheck
For the ith element, say A we handle all As
If it occurs before i too, skip (you handled it already)
Count the same items >= i: `quantity`
Loop the stock to find `#quantity` items.
If after the loop #quantity not reached, return failure
If after the walk of listToCheck reached
return success
If the same items appear one after another the quantity can be determined simply, and the loop becomes simpler.
Related
I have to optimize and algorithm and i noticed that we have a loop like this
while (!floorQueues.values().stream().allMatch(List::isEmpty))
It seems like on each iteration it checks if all of the lists in this map are empty.
The data in the map is taken from a two dimensional array like this
int currentFloorNumber = 0;
for (int[] que : queues) {
List<Integer> list = Arrays.stream(que).boxed().collect(Collectors.toList());
floorQueues.put(currentFloorNumber, list);
currentFloorNumber++;
}
I thought that it will be more optimal if i take the count of elements in the arrays when transforming the data and then check how many times i deleted from the lists as a condition to end the loop
while (countOfDeltedElements < totalCountOfElements)
but when i tested the code it runs slower that before. So i wonder how isEmpty works behind
the scenes to be faster than my solution.
This may depend on the implementation of the class that implements List.
An ArrayList simply checks if there are 0 elements:
/**
* Returns <tt>true</tt> if this list contains no elements.
*
* #return <tt>true</tt> if this list contains no elements
*/
public boolean isEmpty() {
return size == 0;
}
A distinct non-answer: Java performance, and Java benchmarking doesn't work this way.
You can't look at these 5 lines of source code to understand what exactly will happen at runtime. Or to be precise: you have to understand that streams are a very advanced, aka complex thing. Stream code might create plenty of objects at runtime, that are only used once, and then thrown away. In order to assess the true performance impacts, you really have to understand what that code is doing. And that could be: a lot!
The serious answer is: if you really need to understand what is going on, then you will need to:
study the stream implementation in great detail
and worse: you will need to look into the activities of the Just in Time compiler within the JVM (to see for example how that "source" code gets translated and optimised to machine code).
and most likely: you will need to apply a real profiler, and to plenty of experiments.
In any case, you should start reading here to ensure that the numbers you are measuring make sense in the first place.
Normally we have two ways to check if the list is empty or not either list.length() > 0 or !list.isEmpty() .
when we use list.length() what happen at backend it will iterate/go through till the end of list and if the list have big numbers of elements and it will surely going to take long to reach the end .On the other hand, if we use 'list.isEmpty()' then it will check only first element of the list if its their or not (O(1)) and return true/false just on this first index which is obviously fast.
From performance prespective , we should alwayz use isEmpty() as best practice
I would like to sort 2D nodes (points) in two dimensions (x and y) and also to allow fast addition and deletion. I would say that this can be done by two linked lists, but found, that Java's LinkedList hides linkage from user. I.e. if I found some node and delete it from one list, I am unable to delete it fast from another.
Is this solveable or I need to write my own class supporting two dimensions of linkage?
To delete the same object from both lists create a wrapper class like so
class PointWrap{
int id = 0;
Point p = null;
public PointWrap( int inid, Point inp){
id = inid;
p = inp;
}
}
An insert would look like this
tree.put( new PointWrap( id++, point) );
When you iterate through to delete just save the id before the delete occurs. This way you can delete from the other list/tree as well.
I would make a compound data structure.
Will you be reading or writing more? If reading more, use an ArrayList; if writing more, use a LinkedList. Have this structure store int[ ] and enter the values as {x, y} and have this structure sort, after each insertion block, by x value only.
Additionally, maintain an array that is populated with y values, not upon insert, but upon sorting of the x-list have this array populated with the values that are actually in the x-list.
Put all of this into a single class and tie the methods together under 1 hood & holy encapsulation batman!
You can have the class return int[2] from a getByX() or getByY()
A question to ask yourself first is, "Do I absolutely need both lists sorted all the time, or only during read operation blocks?" If your answer is the latter, this will work just fine for you.
Another thing to consider, will you need a queue, deque, stack, or all random access?
I'm a Java newbie with a quick Array vs. ArrayList question. I have an array of objects that can grow or reduce in size, but it's very important for me to maintain the position they were in relative to each other in the array. I'm thinking because of this I need to use Array instead of an ArrayList which can condense/shift elements around if they are removed/added.
The practical example: In my first Java application that I'm slugging through to learn the nuances of this language I'm making a basic poker game simulator. I have Player objects in an array representing the seats they are sitting at, and it's important to know where the dealer button (index) was placed before rotating it. Players being removed or added from an ArrayList will change the indices of the players, and that can throw off the next Player to get it. Dealer button movement is very player-placement specific.
Long story short - is using an Array the best way of handling elements in an array-type structure that need to maintain their position in the array? Is there a better method or logic to accomplish this? I apologize for the simple question but I couldn't find any other alternatives and wanted to confirm that this is the best route to take.
EDIT:
To further clarify, let me give an example of why ArrayList's element movement won't work:
Take three players and their indices in the array:
0 : Player One (Dealer button)
1: Player Two
2: Player Three
If player two (index one) gets up from the table before the dealer button is rotated, depending on the rules player one will keep the button and the blinds will be adjusted accordingly (there's other variants of this rule, but the one I like to use). In an ArrayList, the internal array will be condensed and player three will end up getting the button an extra round before he should. I need to track the empty seat that was active during the hand but was emptied before the round was over and the button moved.
I'm starting to realize that the concept of a "seat" is going to be more complicated, I need to track state on it, including "player just sat down while hand in progress," "player got up while hand in progress," etc. #Stephen P - I think you're right about this, I'm going to need to track them separately and cannot use a simple array structure to determine the logic. Timing of when the elements are added and/or removed is paramount to the application logic, and simply examining if an element is there or not won't cut it.
For the Seats themselves, I'm learning towards ArrayList since the Seats will now always be there, no empties. The Seat will just have a reference to the Player object if one is sitting there as well as WHEN that player arrived. Thanks everyone!
With ArrayList, you can make your players sit tight by using set(int index, T value). You just have to fill the arrayList with nulls first:
List<Player> seats = new ArrayList<>(Collections.nCopies(numPlayers,(Player)null));
seats.set(2,player); // Place a player in the third chair
seats.set(1,null); // Empty the second chair
Long story short - is using an Array the best way of handling elements
in an array-type structure that need to maintain their position in the
array? Is there a better method or logic to accomplish this? I
apologize for the simple question but I couldn't find any other
alternatives and wanted to confirm that this is the best route to
take.
Position shouldn't be your most important criterion for choosing array vs. ArrayList, at least I don't believe it should be.
Arrays are covariant, and more performant most of the time. They mix poorly (if at all) with Java generics which is really kind of a big deal a lot of the time. You cannot create a reference to a new instance of an array of a non-reifiable type (though you can receive one, but buyer beware).
ArrayLists, as a part of the Java Collections API, are invariant. For this reason they work much better with Java generics and, according to Joshua Bloch (Essential Java, 2nd Ed), should be favored much of the time. ArrayLists should often be less performant (and less concise) than arrays. Moreover, as part of the Java Collections API, ArrayLists are more flexible because they extend the List interface which enables you to change implementations from ArrayList to any other List provided that your own class that implements the List is well encapsulated (i.e. the ArrayList is not part of your class's exported API).
There are other differences, of course, but these are the ones that really stand out. If you were really concerned about performance, you could create your own List implementation that was backed by arrays (like ArrayList is) in order to get a feature or the API contract you really wanted. Otherwise, to me, it sounds like you should be using ArrayList (or even other Collection type such as Map (suggested)).
If you have a constant number of seats, you can use either an array or an ArrayAist. If you want to increase the number of seats, you will need an Arraylist, because regular arrays are immutable. See this for more information on the immutability of arrays: Why is an array's length immutable? An ArrayList will never move around its contents if you only use the get(int index) and set(int index, E element)
Also, it is bad practice to let null mean something, even if that something is nothing.
The code:
seat ArrayList initialization
List<Person> seats = new ArrayList<Person>(max_Number_Of_Seats_here);
for(Person person : seats)
{
person = new Person("");
}
//You can then set people like this:
seats.set(seat_index_here, new Person("Darkprozac"));
And have the parameter for the constructor for the class Person be its name.
Person constructor
...
public String name;
public Person(String name)
{
this.name = name;
...
You can then check if the Person's name is "", and if it is, skip that person:
Check if seat is empty
...
for(Person person : seats)
{
if(person.name.equals(""))
{
//do nothing
}
else
{
doSomething();
}
}
...
You can also wrap a Person in a Seat class:
Seat Class
public class Seat
{
public Person person;
public String state;
public Seat(String name)
{
if(name.equals("");
{
state = "empty";
}
else
{
state = "full";
person = new Person(name);
}
}
}
and then modify seat ArrayList initialization and Check if seat is empty accordingly.
Thanks to MrBackend for pointing out that I was wrong about ArrayLists initializing as null.
I would use a map, specifically, a TreeMap.
NavigableMap<Integer, Player> seats = new TreeMap<Integer, Player>();
Integer first = seats.firstKey();
Integer next = seats.nextKey(first);
This gives the benefits of a map, you don't have to worry about seats shifting (even accidentally), and you can still navigate seats easily.
The map manages its own storage (unlike an array) and does not have a risk of shifting indices (unlike an ArrayList).
How do I compare each element in two different sets of data, and then merge certain elements of them into a new set of data?
Some info about my methods below. Note:
Not using java.lang.Collections
In one class I have these calls initializers:
BookCollection collection1 = new BookCollection(100);
BookCollection collection2 = new BookCollection(50);
BookCollection collection3 = new BookCollection(150);
And this call to my method merge(which I am trying to complete)
collection3.merge(collection1, collection2);
Anndd in another class my method merge is trying to compare the two sets of data(collection 1 and 2) and if it finds an elements that are equal, only add 1 of those elements to the new collection. Otherwise, add all of the non-equal elements to the new collection.
Here is what I made, but I know that it isn't working. There is a call to one of my other methods findBook that I will post.
public BookCollection merge(BookCollection c1,BookCollection c2){
//use this. operator to grab other vars
BookCollection cNew = new BookCollection(cNew);
for(String s1: c1)
if (s1.equals(c2)) {
cNew = c1;
}
cNew = c1 + s1;
}
Annddd
private int findBook(String isbn){
// iterate all the Book elements in the collection array
for(int i = 0; i <= collection.length; i++){
// check if the current book isbn matches the one provided argument
if (collection[i].getIsbn().equals(isbn))
return i;
}
return -1;
}
The solution should be far shorter than that.
I'll give you some tips because the idea is not give plain solutions and this question I'm pretty sure is homework.
If the question is homework add 'homework' tag
Tips:
Your main method doesn't have any loop. How are gonna iterate over the collections?
Books as objects they are should have an equals method. If that method is correctly implemented (you should define what is a method begin equals to another), then you just can compare b1.equals(b2)
Collections have contains method to check if it contains (by using equals) other book
Math.min method calculates the minimum between two integers or doubles (there are two versions)
Also, to be complete, if your collections are of a certain type your books should implement hashCode in a compatible way with equals (but my guess is you don't know what hashing is yet, and you'll not use that kind of collections)
So first of all: devise an algorithm. The simpler the better. In plain English.
Just then try to implement that. You'll see the code is much simpler and tidy if you try to program a previous well thought concept.
Edit:
Ensure to know what a Collection is in Java world (tip: is a general interface implemented by several distinct more specific classes).
And don't use the word array unless you are using real arrays (and given your exercise proposal it doesn't seem you need it).
So far I have what's written below but how would I make sure the item to add returns to it's alphabetized spot?
I'm in a beginner class so I cannot use ArrayLists or the methods assoicated with them.
Any sort of help or push in the right direction would be appreciated. Thanks!
The method should follow these instructions:
- Adds an item to the list. This method assumes that the list is already
sorted in alphabetical order based on the names of the items in the list.
- The new item will be inserted into the list in the appropriate place so
that the list will remain alphabetized by names.
In order to accommodate the new item, the internal array must be re-sized
so that it is one unit larger than it was before the call to this method.
public void add(Listable itemToAdd) {
Listable[] items1;
int newlength = items.length+1;
items1 = new Listable [newlength];
for(int i = 0;i<items.length;i++){
items1[i] = items[i];
items1[newlength-1] = itemToAdd;
}
}
That's not bad for a start! There are a number of things we need to do. This line
items1[newlength-1] = itemToAdd;
needs to come out of the loop, and be placed afterwards -- you'll set some array element to this value just once, yes, and not many times?
The copying part is a good start. What you need to do is
Find the location where the new element should go (search through the array, and find the element that the new one should go after)
Copy the elements that go before the new element
Copy the new element
Copy the elements that go after the new element (adjusting their indexes, since they're all one later than they used to be!)
Make sense?
If you're in a beginner class, you may have learned about insertion sort. One of the interesting properties of insertion sort is that despite its poor runtime in the average case (O(n2)), its performance in the best case (a sorted list) is quite good - O(n), in fact. An almost-sorted list would run in the same efficiency class. That might be a way to accomplish what you're trying to do. (It also might be one of the few places you'll ever use insertion sort, so make the most of it.)