Reducing time complexity for the given task - java

I have an item that has a name and a price for it.
Now input for my program contains some list of commands which indicate I can add new item or select an item in the following format:
Add, item-name, item-price --> Adds item-name with price item-price to my list.
Select, , --> select the item name that has lowest price at index k, and prints to output. If multiple items has same price then select the name in ascending order.
Example 1:
Input :
Add, Apple, 4
Add, Ball, 3
Select, ,
Add, Toy, 5
Add, Pen, 1
Select, ,
Output:
Ball, Ball
Explanation:
First we add Apple and Ball. So the items sorted by price [Ball(3), Apple(4)]. Initialize k to 0.
Then Select has appeared. So get item at index k=0 which is Ball. Now increment k to 1 as a selection has occurred.
Then we add Toy and Pen. So the items sorted by price [Pen(1), Ball(3), Apple(4), Toy(5)] . Now k is 1.
Then Select has appeared. So get item at index k=1 which is Ball again. Now increment k to 2 as a selection has occurred.
So output is Ball, Ball.
Example 2:
Input :
Add, Apple, 4
Add, Ball, 3
Select, ,
Select, ,
Add, Toy, 5
Select, ,
Output:
Ball, Apple, Toy
Explanation:
First we add Apple and Ball. So the items sorted by price [Ball(3), Apple(4)]. Initialize k to 0.
Then Select has appeared. So get item at index k=0 which is Ball. Now increment k to 1 as a selection has occurred.
Then Select has appeared. So get item at index k=1 which is Apple. Now increment k to 2 as a selection has occurred.
Then we add Toy. So the items sorted by price [Ball(3), Apple(4), Toy(5)] . Now k is 2.
Then Select has appeared. So get item at index k=2 which is Toy. Now increment k to 3 as a selection has occurred.
So output is Ball, Apple, Toy.
This is the code I tried:
public static void main(String[] args) {
System.out.println(process(Arrays.asList(Arrays.asList("Add", "Apple", "4"), Arrays.asList("Add", "Ball", "3"),
Arrays.asList("Select", "", ""), Arrays.asList("Add", "Toy", "5"), Arrays.asList("Add", "Pen", "1"),
Arrays.asList("Select", "", ""))));
System.out.println(process(Arrays.asList(Arrays.asList("Add", "Apple", "4"), Arrays.asList("Add", "Ball", "3"),
Arrays.asList("Select", "", ""), Arrays.asList("Select", "", ""), Arrays.asList("Add", "Toy", "5"),
Arrays.asList("Select", "", ""))));
}
public static List<String> process(List<List<String>> input) {
List<String> list = new ArrayList<>();
PriorityQueue<Item> pq = new PriorityQueue<>();
int k = 0;
for (List<String> e : input) {
if ("Add".equals(e.get(0))) {
Item a = new Item(e.get(1), e.get(2));
pq.add(a);
} else {
List<Item> sorted = new ArrayList<>();
for (int i = 0; i <= k; i++) {
sorted.add(pq.poll());
}
Item itemAtK = sorted.get(sorted.size() - 1);
list.add(itemAtK.name);
pq.addAll(sorted);
k++;
}
}
return list;
}
}
class Item implements Comparable<Item> {
int price;
String name;
public Item(String name, String p) {
this.name = name;
this.price = Integer.parseInt(p);
}
public int compareTo(Item item) {
int c = price - item.price;
if (c == 0)
c = name.compareTo(item.name);
return c;
}
Here time complexity is I guess n^2*log(n)
How to reduce the time complexity for this code.
Modified code based on stef comments:
public static List<String> process(List<List<String>> input) {
List<String> list = new ArrayList<>();
PriorityQueue<Item> pq = new PriorityQueue<>();
for (List<String> e : input) {
if ("Add".equals(e.get(0))) {
Item a = new Item(e.get(1), e.get(2));
pq.add(a);
} else {
Item itemAtK = pq.poll();
list.add(itemAtK.name);
}
}
return list;
}
Input :
Add, Apple, 4
Add, Ball, 3
Select, ,
Add, Toy, 5
Add, Pen, 1
Select, ,
Expected Output:
Ball, Ball
This program gives wrong output:
Ball, Pen

As someone commented, perhaps what you need is not a PriorityQueue.
Here is an implementation with an unbalanced BST:
public static List<String> process(List<List<String>> input) {
List<String> list = new ArrayList<>();
Item root = null;
int k = 0;
for (List<String> e : input) {
if ("Add".equals(e.get(0))) {
Item a = new Item(e.get(1), e.get(2));
root = Item.insert(root, a);
} else {
Item first = Item.itemAt(root, k);
list.add(first.name);
++k;
}
}
return list;
}
class Item implements Comparable<Item> {
int count;
private Item left;
private Item right;
int price;
String name;
public Item(String name, String p) {
this.name = name;
this.price = Integer.parseInt(p);
}
#Override
public int compareTo(Item item) {
int c = price - item.price;
if (c == 0)
c = name.compareTo(item.name);
return c;
}
public static Item insert(Item root, Item item) {
if (root == null) {
item.count = 1;
return item;
}
int c = item.compareTo(root);
if (c < 0) {
root.left = insert(root.left, item);
} else {
root.right = insert(root.right, item);
}
++root.count;
return root;
}
public static Item itemAt(Item root, int ix) {
if (root == null) {
return null;
}
if (root.left != null) {
if (ix < root.left.count) {
return itemAt(root.left, ix);
}
ix -= root.left.count;
}
if (ix == 0) {
return root;
}
--ix;
if (root.right != null) {
if (ix < root.right.count) {
return itemAt(root.right, ix);
}
}
return null;
}
}
The average complexity is in O(log(n)), but as the tree is unbalanced, there are degenerate cases (when the items are entered sorted).
ERRATA: O(n*log(n))

Related

How to return the position of object by names?

I have a method that count the position of an Item by comparing others Item names, but I wanted to know if there were a simplier way to do it ?
// arr.get(0) : Item0:"nameA"
// arr.get(1) : Item1:"nameB"
// arr.get(2) : Item2:"nameB"
// arr.get(3) : Item3:"nameB"
// arr.get(4) : Item4:"nameC"
// arr.get(5) : Item5:"nameC"
// arr.get(6) : Item6:"nameB"
// If I set (arr, Item2) : should return 2 ("nameB")
// If I set (arr, Item6) : should return 4 ("nameB")
// If I set (arr, Item5) : should return 2 ("nameC")
public int positionOfItemByName(Item[] array, Item item) {
int cpt = 0;
for (int i = 0; i < arr.length; i++) {
if (array[i].name().indexOf( item.name() ) == -1) continue;
cpt++;
if (array[i] == item) break;
}
return cpt;
}
Thanks !
Looking at your requirement, the method name, positionOfItemByName doesn't sound appropriate. From an execution perspective, it doesn't matter which name you choose. However, the name should be as self-descriptive as possible.
Given below is the logic to meet your requirement:
public static int countOfItemByNameAndPosition(Item[] array, Item item) {
List<Item> arr = new ArrayList<Item>(Arrays.asList(array));
int cpt = 0;
int index = arr.indexOf(item);
if (index != -1) {
for (int i = 0; i < arr.size() && i <= index; i++) {
if (arr.get(i).name.equals(item.name)) {
cpt++;
}
}
}
return cpt;
}
Demo
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Item {
String name;
public Item(String name) {
this.name = name;
}
#Override
public String toString() {
return "Item [name=" + name + "]";
}
}
public class Main {
public static void main(String[] args) {
Item item0 = new Item("nameA");
Item item1 = new Item("nameB");
Item item2 = new Item("nameB");
Item item3 = new Item("nameB");
Item item4 = new Item("nameC");
Item item5 = new Item("nameC");
Item item6 = new Item("nameB");
Item[] array = { item0, item1, item2, item3, item4, item5, item6 };
System.out.println(countOfItemByNameAndPosition(array, item2));
System.out.println(countOfItemByNameAndPosition(array, item6));
System.out.println(countOfItemByNameAndPosition(array, item5));
}
public static int countOfItemByNameAndPosition(Item[] array, Item item) {
List<Item> arr = new ArrayList<Item>(Arrays.asList(array));
int cpt = 0;
int index = arr.indexOf(item);
if (index != -1) {
for (int i = 0; i < arr.size() && i <= index; i++) {
if (arr.get(i).name.equals(item.name)) {
cpt++;
}
}
}
return cpt;
}
}
Output:
2
4
2
Using Stream API:
public static int countOfItemByNameAndPosition(Item[] array, Item item) {
List<Item> arr = new ArrayList<Item>(Arrays.asList(array));
return (int) IntStream.range(0, arr.indexOf(item)+1).filter(i -> item.name.equals(arr.get(i).name)).count();
}
Demo
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
class Item {
String name;
public Item(String name) {
this.name = name;
}
#Override
public String toString() {
return "Item [name=" + name + "]";
}
}
public class Main {
public static void main(String[] args) {
Item item0 = new Item("nameA");
Item item1 = new Item("nameB");
Item item2 = new Item("nameB");
Item item3 = new Item("nameB");
Item item4 = new Item("nameC");
Item item5 = new Item("nameC");
Item item6 = new Item("nameB");
Item[] array = { item0, item1, item2, item3, item4, item5, item6 };
System.out.println(countOfItemByNameAndPosition(array, item2));
System.out.println(countOfItemByNameAndPosition(array, item6));
System.out.println(countOfItemByNameAndPosition(array, item5));
}
public static int countOfItemByNameAndPosition(Item[] array, Item item) {
List<Item> arr = new ArrayList<Item>(Arrays.asList(array));
return (int) IntStream.range(0, arr.indexOf(item) + 1).filter(i -> item.name.equals(arr.get(i).name)).count();
}
}
Output:
2
4
2
Feel free to comment in case of any doubt/issue.
Another option is to create equals method to your class that will look like
public boolean equals(Object o) {
if(!(o instanceof Item))
return false;
Item other = (Item)o;
//you can change it to any compare method you want
return other.name.equals(this.name);
}
And then just use the function indexOf and it will use your method to compare.
Yes, there is. First, you can just return i, the variable cpt is redundant. Second, you don't need two checks inside the loop. You can combine both with the String#equals(String) method that checks the equality of two strings. Return -1 if the name cannot be found. Negative numbers are not valid indices of arrays/collections, thus good values to say "not found".
public int positionOfSameName(ArrayList<Item> arr, Item item) {
for (int i = 0; i < arr.size(); i++) {
if (arr.get(i).name().equals(item.name()) {
return i;
}
}
return -1;
}
Edit: After your clarification that you want to count the occurrences of the given name in the given array, you need to work with an additional variable.
public int positionOfSameName(ArrayList<Item> arr, Item item) {
int counter = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr.get(i).name().equals(item.name()) {
counter++;
}
}
return counter;
}
FYI: You should consider changing the name of the method. As it is right now it's not doing what it says by its name.

How to get all the possible matches of two lists?

For example, I have a list which contains some Lecture instances, each lecture has a certain number of students attending this lecture and another list which contains some Classroom instances, each classroom has a maximum capacity.
Now I intend to assign each lecture in lecture list with a classroom in classroom list, all lectures in lecture class should have a classroom, then create a map to store this possibility.
And I want to return all these possible matches in the form of a set.
For example:
Classroom List: [Classroom1(50),Classroom2(70),Classroom3(80)]
Lecture list: [Lecture1(50), Lecture2(70), Lecture3(50)]
Then we have 3 possible maps, which are:
{lecture1:classroom1, lecture2:classroom2, lecture3:classroom3} and
{lecture1:classroom1, lecture2:classroom3, lecture3:classroom2} and
{lecture1:classroom2, lecture2:classroom3, lecture3:classroom1}
After that, all possible maps should be stored in a set.
I am new to programming and has not learned algorithm yet, maybe that's why I'm so struggled on this, I'd be grateful if someone could help me solve this problem.
What you seem to be after is something known as the cartesian product.
See https://en.wikipedia.org/wiki/Cartesian_product
You can do this with Java 8 streams
All permutations
// Just substitute the types and values for Lecture and Classroom instances
// I'm not going to do this for you
final List<String> first = Arrays.asList("foo","bar","baz");
final List<String> second = Arrays.asList("spam","ham","eggs");
final Set<Map.Entry<String,String>> objects =
first
.stream()
.flatMap(f ->
second
.stream()
.map(s -> new AbstractMap.SimpleEntry<>(f, s)))
.collect(Collectors.toSet());
Your 'objects' set is going to contain Abstract entry maps which hold your combinations.
Set[
Map{foo : spam}
Map{foo : ham}
Map{foo : eggs}
Map{bar : spam}
Map{bar : ham}
Map{bar : eggs}
Map{baz : spam}
Map{baz : ham}
Map{baz : eggs}
]
Groups of combinations
If you actually want 3 items in your set, you can do an intermediate collect on the second stream to collect into a data structure of your choice. Below shows that for a list, as I've already shown use of Collectors.toSet()
final Set<List<AbstractMap.SimpleEntry<String,String>>> objects =
first
.stream()
.map(f ->
second
.stream()
.map(s -> new AbstractMap.SimpleEntry<>(f, s))
.collect(Collectors.toList()))
.collect(Collectors.toSet());
Your 'objects' set is going to contain a list of Abstract entry maps which hold your combinations.
Set[
List(
Map{foo : spam}, Map{foo : ham}, Map{foo : eggs}
),
List(
Map{bar : spam}, Map{bar : ham}, Map{bar : eggs}
),
List(
Map{baz : spam}, Map{baz : ham}, Map{baz : eggs}
)
]
This illustrates a simple cartesian product algorithm using Java 8 in a single functional statement. Should you wish to add any clauses or exclusions, you can use filter or any of the other higher order functions to manipulate the stream.
So i got sucked in to this one and wrote a working solution
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
class ClassMatcher {
//The set of all possible matchings.
static ArrayList<ArrayList<Pair>> set = new ArrayList<ArrayList<Pair>>();
// The current matching being built
static ArrayList<Pair> cur = new ArrayList<Pair>();
public static void main(String[] args) {
Lecture[] l = { new Lecture(50, 1), new Lecture(70, 2), new Lecture(50, 3)};
ArrayList<Classroom> c = new ArrayList<>(Arrays.asList(
new Classroom(50, 1), new Classroom(70, 2),
new Classroom(100, 3)));
for (int i = 0; i < l.length; i++) {
//Fill with dummy values
cur.add(new Pair(new Classroom(-1, -1), new Lecture(-1, -1)));
}
// Sort the arrays to save work in rec()
Arrays.sort(l);
//Sort classrooms in descending order
Collections.sort(c, new Comparator<Classroom>() {
#Override
public int compare(Classroom o1, Classroom o2) {
return o1.compareTo(o2) * -1;
}
});
recursive(l, c, 0);
// Print all the sets
for (int i = 0; i < set.size(); i++) {
System.out.print("{");
for (int j = 0; j < set.get(i).size(); j++) {
System.out.print("Lecture " + set.get(i).get(j).l + ": "
+ "Classroom " + set.get(i).get(j).c);
if (j < set.get(i).size() - 1) {
System.out.print(", ");
} else {
System.out.print("}");
}
}
System.out.println();
}
}
public static void recursive(Lecture[] lectureList,
ArrayList<Classroom> classroomList, int curLecture) {
for (int i = 0; i < classroomList.size(); i++) {
// if the classroom is smaller than the lecture we cna stop as the
// lists are sorted so all other lectures will be to big for the
// current classroom
if (lectureList[curLecture].size > classroomList.get(i).size) {
return;
}
//Match the current classroom to the current lecture and add to the working matching
cur.set(curLecture, new Pair(classroomList.get(i), lectureList[curLecture]));
//If there are more lectures to do then remove the used classroom and recursively call.
if (curLecture < lectureList.length - 1) {
Classroom tmp = classroomList.remove(i);
recursive(lectureList, classroomList, curLecture + 1);
classroomList.add(i, tmp);
}
// If no Lectures left then add this matching to the set of all matchings.
else {
ArrayList<Pair> copy = (ArrayList<Pair>) cur.clone();
set.add(copy);
}
}
}
}
class Classroom implements Comparable<Classroom> {
int size;
int number;
public Classroom(int s, int n) {
size = s;
number = n;
}
#Override
public int compareTo(Classroom o) {
return Integer.compare(this.size, o.size);
}
public String toString() {
return number + " (" + size + ")";
}
}
class Lecture implements Comparable<Lecture> {
int size;
int number;
public Lecture(int s, int n) {
size = s;
number = n;
}
#Override
public int compareTo(Lecture o) {
return Integer.compare(this.size, o.size);
}
public String toString() {
return number + " (" + size + ")";
}
}
class Pair {
Classroom c;
Lecture l;
public Pair(Classroom c, Lecture l) {
this.c = c;
this.l = l;
}
}
This gives the output
{Lecture 1 (50): Classroom 3 (100), Lecture 3 (50): Classroom 1 (50), Lecture 2 (70): Classroom 2 (70)}
{Lecture 1 (50): Classroom 2 (70), Lecture 3 (50): Classroom 1 (50), Lecture 2 (70): Classroom 3 (100)}
{Lecture 1 (50): Classroom 1 (50), Lecture 3 (50): Classroom 3 (100), Lecture 2 (70): Classroom 2 (70)}
{Lecture 1 (50): Classroom 1 (50), Lecture 3 (50): Classroom 2 (70), Lecture 2 (70): Classroom 3 (100)}
Code below will give you all the matches, you can use them like whatever you want
HasMap<Integer, Integer> match = new HashMap<Integer, Integer>();
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(classroom[i] >= lecture[j]) {
match.add(lecture[j], classroom[i]);
}
}
}
if you want seperate maps like for every classroom or lecture you can try this(example for classrooms)
HashMap<Integer, Integer> classroom1 = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> classroom2 = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> classroom3 = new HashMap<Integer, Integer>();
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(i == 0) {
if(classroom[i] >= lecture[j]) {
classroom1.add(lecture[j], classroom[i]);
}
}
if(i == 1) {
if(classroom[i] >= lecture[j]) {
classroom2.add(lecture[j], classroom[i]);
}
}
if(i == 2) {
if(classroom[i] >= lecture[j]) {
classroom3.add(lecture[j], classroom[i]);
}
}
}
}
After this you can create map of maps. Don't mind about correcting me or adding something. Have a good day!
The algorithm in itself might look something like this using an nested for each loop:
public Set<Object[]> allocateRooms(List<Lecture> lectures, List<ClassRoom> classRooms){
Set<Object[]> returnSet = new LinkedHashSet<>();
for(Lecture l: lectures){
for (ClassRoom c: classRooms){
Object[] n = new Object[2];
n[0] = c;
n[1] = l;
returnSet.add(n);
}
}
return returnSet;
}
Here is an answer using Maps instead of arrays:
public Set<Map<Lecture, ClassRoom>> allocateRooms(List<Lecture> lectures, List<ClassRoom> classRooms){
Set<Map<Lecture, ClassRoom>> returnSet = new LinkedHashSet<>();
for(Lecture l: lectures){
for (ClassRoom c: classRooms){
Map<Lecture, ClassRoom> n = new HashMap<>();
n.put(l,c);
}
}
return returnSet;
}
Here is an example with sorted data collections:
public Set<Map<Lecture, ClassRoom>> allocateRooms(List<Lecture> lectures, List<ClassRoom> classRooms){
List<ClassRoom> sortedClassRooms = classRooms
.stream().sorted(Comparator.comparingInt(a -> a.getId())).collect(Collectors.toList());
List<Lecture> sortedLectures = lectures
.stream().sorted(Comparator.comparingInt(a -> a.getId())).collect(Collectors.toList());
Set<Map<Lecture, ClassRoom>> returnSet = new LinkedHashSet<>();
for(Lecture l: sortedLectures){
for (ClassRoom c: sortedClassRooms){
Map<Lecture, ClassRoom> n = new HashMap<>();
n.put(l,c);
}
}
return returnSet;
}

New to java. How to add the item to specific repositories using a text file

My main class
int n, p;
String d;
manager m = new manager();
Scanner f = new Scanner(i.class.getResourceAsStream("product.txt"));
while (f.hasNextLine()) {
String[] s = f.nextLine().split(",");
n = Integer.parseInt(tokens[0]);
d = s[1];
p = Integer.parseInt(s[2]);
Item item = new Item(itemNo, description, price);
m.addItems(item);
if (s[3].contains("1")) {
m.addRep(1, item);
}
if (s[3].contains("2")) {
m.addRep(2, item);
}
if (s[3].contains("3")) {
m.addRep(3, item);
}
}
}
Example from my text File:
34,table,1200,12
14,sofa,2950,123
format of s[3] is e.g. "12" and "123" to represent that item is in repositories with ID's 1, 2 and 3
Error I am getting
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:643)
at java.util.ArrayList.add(ArrayList.java:455)
at dadsaassi.manager.addRep(manager.java:26)
Java Result: 1
My Item class
public int itemNum = 0;
public String des = "";
public int price = 0;
public Item(int i, String d, int p) {
itemNum = i;
des = d;
price = p;
}
My manager class
private ArrayList<Item> rep = new ArrayList<Item>();
private ArrayList<Item> list = new ArrayList<Item>(); //creates ArrayList
public void addItems(Item item) {
list.add(item);
}
public void addRep(int num, Item item) {
rep.add(num, item);
List is 0 index based. At manager.java, whenever you try to add at 1 index of rep ArrayList than rep.size()>0 is true.
m.addItemToRepository(1, item);
So, it throws IndexOutOfBoundsException. Look at docs of List.add(element, index) method.
IndexOutOfBoundsException - if the index is out of range (index < 0 ||
index > size())
The solution is, you should not mention index at rep List
m.addItemToRepository(item); //It will start from 0
or,
m.addItemToRepository(0, item);// Although index is here redundant.
Edit: If you need repository number, you can also use Map<Integer, Item>, where Integer is the repository number.
Map<Integer, Item> rep = new HashMap<Integer, Item>();
public void addItemToRepository(int num, Item item) {
rep.put(num, item);
}

ArrayList<Item> (where Item is inner class) adding wrong

I have a class called Bag2 and it has inner class called Item. Bag2 has variable ArrayList aList and function called "add". It's adding wrong by repeat adding duplicate value.
Here is my code:
import java.util.ArrayList;
public class Bag2 {
public Bag2(){}; // Constructor
/**
* Inner class
*
*/
public class Item implements Comparable<Item> {
String name;
int quantity;
public Item(String name, int quantity) { // Constructor
this.name = name;
this.quantity = quantity;
}
#Override
public String toString() {
return name + " : " + quantity;
}
#Override
public int compareTo(Item o) {
return name.compareToIgnoreCase(o.name);
}
}
public ArrayList<Item> aList = new ArrayList<>();
public void add(String itemName){
Bag2 bag2 = new Bag2();
Bag2.Item item = bag2.new Item(itemName.toUpperCase(), 1);
if (aList.isEmpty()){
aList.add(item);
} else
{
for(int i = 0; i < aList.size();i++){
if (item.compareTo(aList.get(i))==0){
aList.get(i).quantity++;
}else {
aList.add(item); // Built inn add-function
break; // add one time only and the size increases
}
}
}
}
}
And here is my test :
public class Bag2Test {
public static void main(String[] args) {
Bag2 bag = new Bag2();
Bag2.Item[] anArray =
{
bag.new Item("A", 1),
bag.new Item("B", 1),
bag.new Item("C", 1),
bag.new Item("D", 1),
bag.new Item("a", 1),
bag.new Item("F", 1),
bag.new Item("b", 1),
bag.new Item("e", 1),
bag.new Item("a", 1)
};
for (int i = 0; i<anArray.length; i++ ){
bag.add(anArray[i].name); //
}
System.out.println("\nA list contains : ");
for (int i = 0; i<bag.aList.size(); i++) {
System.out.println(bag.aList.get(i));
}
}
}
and output:
A list contains :
A : 3
B : 1
C : 1
D : 1
A : 1
F : 1
B : 1
E : 1
A : 1
Your add function is broken because it can trigger the statement if (item.compareTo(aList.get(i))==0) for one i value and still add it for another value. While there are more elegant and robust solutions for you program including overriding equals()and hashCode() and using a Set instead of a list, that would result in a generic bag implementation and I posted the shortest fix for your problem.
public void add(String itemName)
{
Bag2 bag2 = new Bag2();
Bag2.Item item = bag2.new Item(itemName.toUpperCase(), 1);
if (aList.isEmpty())
{
aList.add(item);
} else
{
boolean existing = false;
for(int i = 0; i < aList.size();i++)
{
if (item.compareTo(aList.get(i))==0)
{
aList.get(i).quantity++;
existing=true;
break;
}
}
if(!existing) {aList.add(item);}
}
}
Let's say you add the following items : A,B,C
now your list is : A:1, B:1, C:1
In your add logic you check if the current item is the same one, otherwise you add the item. So if we now try to add item C again your list will look like this: A:1, B:1, C:1, C:1
This is because you are checking item by item. Before adding the new item you need to check that it does not exist in the ENTIRE list and only then add it. (e.g. When adding C to the above list the first loop iteration (i=0) will execute the code in the else block since C and A are different and C will be added although it does exist in the list)

How to add items to arraylist and modify a feature

I am trying to add items to my array list with an action listener on a pop up window. You can see the action listener here. The problem that I am now having is I do not know how to add the inputs to my array list. Part of this problem is that I need to set my item number to 1 higher than the highest in my list. My array list is named as such:
private static ArrayList<InventoryItem> inventory = new ArrayList<>();
and the class for InventoryItem looks like this:
public class InventoryItem { //Delcare variables below
DecimalFormat formatted = new DecimalFormat("#,###.00");//set up decimal format for displaying 12.34 type values
String itemName;
int itemNumber;
public String getItemName() {
return itemName;
}
public int getItemNumber(){
return itemNumber;
}
int inStock;
double unitPrice;
double value;
double restockingFee;
double inventoryValue;
public InventoryItem(String itemName, int itemNumber, int inStock, double unitPrice) { //declare variables for this class
this.itemName = itemName;
this.itemNumber = itemNumber;
this.inStock = inStock;
this.unitPrice = unitPrice;
stockValue(); //call stock value
}
}
So my question is two parts. The first is how do I get my itemNumber to increment to 1 higher than the highest? Do I simply do a bubble sort to find the highest? And the second part is how do I get it to add all items, including this incremented itemNumber, into my original arraylist?
Note
If needed I can paste my code in it's entirety on pastebin as it is somewhat large.
EDIT: Per #Prabhakaran I have added some code and I am almost there. I have almost gotten this to work, however when I start to look through my list I do not see the added feature so how can I be sure that I am actually adding it?
String newItemName = String.valueOf(xField);
String text1 = yField.getText();
String newInventoryAmount = String.valueOf(text1);
int newNumber = Integer.parseInt(newInventoryAmount);
String text2 = zField.getText();
String newUnitPrice = String.valueOf(text2);
double newPrice = Double.parseDouble(newUnitPrice);
for (int i = 0; i >= inventory.size(); i++) {
inventory.get(inventory.size() ).getItemNumber();
int newItemNumber;
newItemNumber = i + 1;
InventoryItem item = new InventoryItem(newItemName, newItemNumber, newNumber, newPrice);
inventory.add(item);
What am I missing here? Shouldn't this simply add an item to my arraylist? I know it must be something really easy, I just can't seem to figure it out.
Here is my sort by ItemName:
static ArrayList sortInventory(ArrayList<InventoryItem> unsorted) {
ArrayList<InventoryItem> sorted = new ArrayList<>(); //create new array list to sort
InventoryItem alpha = null;
int lowestIndex = **-1**;
while (unsorted.size() > 0) { //while my unsorted array is less than 0 do the following
for (int i = 0; i < unsorted.size(); i++) { //increment through
if (alpha == null) {
alpha = unsorted.get(i); //get the next line in the inventoryItem array
lowestIndex = i;
} else if (unsorted.get(i).itemName.compareToIgnoreCase(alpha.itemName) < 0) { //compare items to determine which has a higher value
alpha = unsorted.get(i);
lowestIndex = i;
}
}
sorted.add(alpha); //reset the index so it will loop until there are no more items in the unsorted array
unsorted.remove(lowestIndex);
alpha = null;
lowestIndex = **0**;
}
return sorted; //return the sorted arraylist
}
EDIT: Corrected the lowestIndex and it goes good as gold.
Do like this
private static ArrayList<InventoryItem> inventory = new ArrayList<>();
String newItemName = String.valueOf(xField);
String newInventoryNumber = String.valueOf(yField);
int newNumber = Integer.parseInt(newInventoryNumber);
String newUnitPrice = String.valueOf(zField);
double newPrice = Double.parseDouble(newUnitPrice);
InventoryItem item =new InventoryItem(newItemName , newInventoryNumber , newNumber , newUnitPrice ) ;
inventory.add(item);
update
class SimpleComparator implements Comparator<InventoryItem> {
#Override
public int compare(InventoryItem o1, InventoryItem o2) {
return new Integer(o1.getItemNumber()).compareTo(o2.getItemNumber());
}
}
//Sorting based on the itemNumber.
Collections.sort(inventory,new SimpleComparator());
int newItemNumber = inventory.get(inventory.size() - 1).getItemNumber();
newItemNumber ++;
You could create your own ArrayList with Observer support:
public class InventoryItemArrayList extends ArrayList {
private static final long serialVersionUID = 4550719458611714650L;
private List listeners = new ArrayList();
public void addInventoryItemAddedListener(InventoryItemAddedListener listener) {
this.listeners.add(listener);
}
#Override
public boolean add(InventoryItem e) {
boolean add = super.add(e);
fireInventoryItemAdded(e);
return add;
}
private void fireInventoryItemAdded(InventoryItem e) {
for (InventoryItemAddedListener element : listeners) {
element.inventoryItemAdd(e);
}
}
#Override
public void add(int index, InventoryItem element) {
super.add(index, element);
fireInventoryItemAdded(element);
}
#Override
public boolean addAll(Collection c) {
boolean addAll = super.addAll(c);
fireInventoryItemAdded(c);
return addAll;
}
private void fireInventoryItemAdded(Collection c) {
for (InventoryItem inventoryItem : c) {
fireInventoryItemAdded(inventoryItem);
}
}
#Override
public boolean addAll(int index, Collection c) {
boolean addAll = super.addAll(index, c);
fireInventoryItemAdded(c);
return addAll;
}
}

Categories