i am looking for a way to check if an array contains more than 1 instances of the same object. I've been looking around but can't seem to find anything in the javadoc nor stackoverflow.
I am creating a monopoly board game (or in danish, matador) where the fee from landing on one of the fields differs depending on how many of that type of field the player owns.
I have a list in my player class in which i put all the fields that the player buys:
public List<OwnableField> ownsList = new ArrayList<>();
public void buy(OwnableField ownable) {
pay(ownable.getPrice());
ownsList.add(ownable);
}
And then i have this method in the specific field class, in which i am working on an if statement to set the fee:
public int fee;
public int feeCalc(int diceScore) {
if(this.getOwner().ownsList.(whatever checks for duplicate object in array)){
fee = 200 * diceScore;
} else {
fee = 100 * diceScore;
}
return fee;
}
If you have a proper equals and hash code defined then you can use sets to achive that
List list = ...
if(new HashSet(list).size().equals(list.size()){
//same size
} else {
//there was a duplicated element
}
If you want to check for one specific object only you could do it with:
final Object someObject = ...
List list = ...
int size = FluentIterable.from(list).filter(new Predicate<Object>() {
#Override
public boolean apply(Object input) {
return input == someObject;
}
}).size();
if(size > 1) {
//there is a duplicated element
}
Or, if you are looking for an instance of a class, then try:
List list = ...
int size = FluentIterable.from(list).filter(Predicates.instanceOf(YourClass.class)).size();
if(size > 1) {
//there is a duplicated element
}
Related
I have list which contains a property class object, In the list i have 3 status
not_paid
paid
part_paid
I want to sort my list below mentioned order.
First - not_paid
second- part_paid
third -paid
How can I sort my list using Comparator class.?
public static Comparator<OrderHistoryItemData> COMPARE_BY_PAYMENT = new Comparator<OrderHistoryItemData>() {
public int compare(OrderHistoryItemData one, OrderHistoryItemData other) {
String p1 = one.getAttributes().getFieldPaymentStatus();
String p2 = other.getAttributes().getFieldPaymentStatus();
if (p1.equals(p2)) {
return 0;
}
if (p1.equals("not_paid") && (p2.equals("part_paid") || p2.equals("not_paid"))) {
return -1;
}
if (p1.equals("not_paid") && p2.equals("not_paid")) {
return -1;
}
return 1;
}
};
This is my Code. i am getting below order using this code.
paid-->not_paid-->part_paid
This is my Update Code. I got my result.
public static Comparator<OrderHistoryItemData> COMPARE_BY_PAYMENT = new Comparator<OrderHistoryItemData>() {
public int compare(OrderHistoryItemData one, OrderHistoryItemData other) {
String p1 = one.getAttributes().getFieldPaymentStatus();
String p2 = other.getAttributes().getFieldPaymentStatus();
if (p1.equals(p2)) {
return 0;
}
if (p1.equals("not_paid") && (p2.equals("part_paid") || p2.equals("paid"))) {
return -1;
}
if (p1.equals("part_paid") && p2.equals("paid")) {
return -1;
}
return 1;
}
};
To avoid complex comparator, I encourage you to export your statuses to an enum. (Plus this will work if you will add more statuses in the future, without the need to change logic in your comparator):
enum PaymentStatus { // Write them in order you want to be sorted
NOT_PAID,
PART_PAID,
PAID
}
Then sorting will be as simple as :
list.sort(Comparator.comparing(item ->item.getAttributes().getFieldPaymentStatus()));
What you can do is first mapping the strings to integers in the desired order, and then simply subtracting them from eachother.
private static Comparator<Payments> comparator = new Comparator<Payments>() {
// Use this mapping function to map the statuses to ints.
// The lowest number comes first
private int map(String str) {
switch (str) {
case "not_paid":
return 0;
case "part_paid":
return 1;
case "paid":
return 2;
default:
return 3;
}
}
// Alternatively, you can use the Map interface to define the sorting
// order.
#Override
public int compare(Payments o1, Payments o2) {
return map(o1.status) - map(o2.status);
}
};
I suggest – Schidu Luca already mentioned it in his answer – that you use enums to define a fixed set of known values, like payment statuses. This provides compile-time safety.
Note: I wouldn't, however, suggest to bind the enum declaration order to the sorting order.
I am trying to figure out how I can turn my 4 basic pseudocode methods inside of my perfect hash class into workable methods that will eventually be used inside of a main method of my PerfectHash class. I know I haven't created the instance of the class yet, but I will.
You know like when you call the 4 methods using a stack, for example, you input parameters inside the methods, but my application will be able to take the key that's entered by the user and insert, fetch, delete, or update on it inside of the structure.
Do I need to put more thought into these methods or is the pseudocode enough to work for now? Here's what I have done so far. I know the first class compiles fine, but I am having trouble with the second class as I have already indicated above.
public class PerfectHash
{
private StadiumTickets[] data;
public boolean insert(StadiumTickets newStadiumTicket)
{
// the direct insert hashed algorithm
pseudoKey = preProcessing(targetKey);
ip = pseudoKey; // direct hashing function
// insert the new ticket
data[ip] = newStadiumTicket.deepCopy();
}
public StadiumTickets fetch(String targetKey)
{
// the fetch algorithm
// access the primary storage area
pseudoKey = preprocessing(targetKey);
ip = pseudoKey; // direct hashing function
if(data[ip]== null)
{
return null;
}
else
{
return data[ip].deepCopy();
}
}
public boolean delete(String targetKey)
{
// the delete direct hashed algorithm
// access the primary storage area
pseudoKey = preprocessing(targetKey);
ip = pseudoKey; // direct hashing function
if(data[ip]== null)
{
return false;
}
else
{
data[ip]= null;
return true;
}
}
public boolean update(String targetKey, StadiumTickets newStadiumTicket)
{
// the update direct hashed algorithm
if(delete(targetKey) == false)
return false;
else
{
insert(newStadiumTicket)
return true;
}
}
}
import java.util.Scanner;
public class StadiumTickets
{
int ticketNumber; // keyfield
String purchaserName;
public void input()
{
Scanner input= new Scanner(System.in);
// key values ranges between 2000 to 100,000
System.out.print("Please enter a ticket number between 2000 to 100,000: ");
// a variable to hold the answer
ticketNumber= input.nextInt();
// error checking to make sure the user doesn't enter a key outside of the lower or upper ranges
if(ticketNumber < 2000 && ticketNumber > 100000)
System.out.println("This number is not a valid entry to input into the structure.");
}
public StadiumTickets(int ticketNumber, String purchaserName)
{
this.ticketNumber= ticketNumber;
this.purchaserName= purchaserName;
}
public StadiumTickets deepCopy()
{
StadiumTickets clone= new StadiumTickets(ticketNumber, purchaserName);
return clone;
}
}
I have a class
class polygon
{
private String name;
private int quantity;
// default constructor
private polygon()
{ }
public String get name() {
return name;
}
public void setname(String name) {
this.name = name;
}
public int getquantity() {
return quantity;
}
public void setquantity(int quantity) {
this.quantity = quantity;
}
}
and also I have a map like this:
LinkedHashMap<Integer, polygon> polymap = new LinkedHashMap<Integer, polygon>();
I have to ask two questions:
How can I find if there is a member with specific value which has the name like "square"?
How can I get all the member with the lowest quantity?
Thanks.
What we have learned from comments and updates: Polygon is a class with members String name (possibly but not necessarily unique) and int quantity (no restriction). There is also a timestamp, and this Integer is used as a key in the
Map<Integer,Polygon> polymap
To find all Polygons with a given name:
for( Polygon polygon: polymap.values() ){
if( polygon.getName().equals( givenName ) ){ //... }
}
Now this is a sequential search and may take some time if the number of entries is very big. Assuming names are unique, O(1) access time can be achieved by creating another Map in parallel to polymap, mapping name strings to Polygon objects. (Consider the additional effort for removing, but Map.remove( ., . ) should help.)
To find all Polygons with the minimum quantity, determine the minimum while keeping a set of the Polygons with that minimum:
int min = Integer.MAX_VALUE;
Set<Polygon> polyset = new HashSet<>();
for( Polygon polygon: polymap.values() ){
int qtty = polygon.getQuantity();
if( qtty < min ){
min = qtty;
polyset.clear();
polyset.add( polygon );
} else if( qtty == min ){
polyset.add( polygon );
}
}
Again, a sequential search, but here a second map will require a multimap, i.e., a Map<Integer,Collection<Polygon>>.
LinkedHashMap<Integer, polygon> polymap = new LinkedHashMap<Integer, polygon>();
How can I find if there is a member with specific value which has the name like "square"?
The containsValue() uses equals method for find the match. You can override the equals() method of the polygon class. Then you can use the containsValue(new polygon()) to find whether the value exist or not. The equals method implementation will be completely depended on the name field of the polygon class. Something like this:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof polygon)) return false;
polygon polygon = (polygon) o;
if (!name.equals(polygon.name)) return false;
return true;
}
Note: You are overriding the equals() method of the class, so could have some side affects on how you are using it at other places in your application.
How can I get all the member with the lowest quantity?
I would suggest you maintain a separate PriorityQueue for finding lowest quantity polygon. Provide a custom Comparator while initializing the queue.
I have a class called Polynomial with an ArrayList made up of term objects, there is an external file that is read by a Scanner object in my test class. The Scanner reads the line for 4 different key words and acts accordingly. ex. INSERT 3 2. Would call my insert method and print out 3x^2. Now I have a delete method with two parameters. When I call the method in the test class nothing happens, the same thing gets printed and nothing has been removed. Am I missing something or doing it wrong all together? Any help is greatly appreciated.
public void delete (int coeff, int expo)
{
for (int i = 0; i<terms.size(); i++)
{
Term current = terms.get(i);
terms.remove(current.getCoeff());
terms.remove(current.getExpo());
}
}
I also have a Term class that creates a term object, and has two methods to get the coefficient and exponent.
Here is a snippet of my test class:
public static void main(String[] args) throws IOException
{
// TODO code application logic here
Polynomial polyList = new Polynomial();
Scanner inFile = new Scanner(new File("operations2.txt"));
while(inFile.hasNext())
{
Scanner inLine = new Scanner(inFile.nextLine());
String insert = inLine.next();
if(insert.equals("INSERT"))
{
int coeff = inLine.nextInt();
int expo = inLine.nextInt();
polyList.insert(coeff, expo);
}
if(insert.equals("DELETE"))
{
int coeff = inLine.nextInt();
int expo = inLine.nextInt();
polyList.delete(coeff, expo);
}
}
System.out.println(polyList.toString());
}
}
Edit: this is a sample of the .txt file that is being read by the scanner class:
INSERT 3 2
INSERT 4 4
INSERT 1 6
INSERT 2 0
INSERT 5 2
INSERT 6 3
PRODUCT
DELETE 3 2
INSERT 2 7
DELETE 4 4
INSERT 4 10
Edit: Here is the Term class:
class Term
{
//instance vars
private int coefficient;
private int exponent;
public Term(int coeff, int expo)
{
coefficient = coeff;
exponent = expo;
}
public int getCoeff()
{
return coefficient;
}
public int getExpo()
{
return exponent;
}
#Override
public int hashCode()
{
return coefficient + exponent;
}
#Override
public boolean equals(Object o)
{
if (!(o instanceof Term))
{
return false;
}
Term t = (Term)o;
return coefficient == t.coefficient && exponent == t.exponent;
}
}
If your delete() method is trying to delete the Twrm with the specified coefficients, I recommend the following:
Override the equals() method to return true if the argument is a Term with the same coefficient and exponential
Override the hashCode() method to return a hash based on the same two values
Since the equals() method should make a value comparison, such an implementation is quite reasonable.
Once you've done that, your delete method becomes one line:
terms.remove(new Term(coeff, expo));
The implementation should look like this:
// in the Term class
#Override
public boolean equals(Object o) {
if (!(o instanceof Term)
return false;
Term t = (Term)o;
return coeff == t.coeff && expo == t.expo;
}
Although overriding the hashCode method is not strictly required to make your code work, it is good practice, so here's an example impl:
#Override
public int hashCode() {
return 31 * coeff + expo;
}
You're not trying to remove the Term from the terms list, but rather trying to remove the coefficient and exponent.
for (int i = 0; i<terms.size(); i++)
{
Term current = terms.get(i); // Your list contains Term objects
terms.remove(current.getCoeff()); // but you are try to removing a coefficient
terms.remove(current.getExpo()); // and an exponent
}
Just a general note also that removing this way will not work because i will be getting larger and your list will be getting smaller. So by the time you get to remove the last term for example (where i = terms.size() - 1), there will only be 1 item left in the list. If you're trying to remove all of the items, consider the list's clear method.
Why does your delete method take the arguments coeff and expo ....
...it does not do anything with them.
In fact, the delete method looks very suspicious. You will need to give more detail on what the terms array looks like, right now it makes no sense.
rolfl
I have two Collection objects, I want to associate each object of these two in a readable way (HashMap, Object created on purpose, you choose).
I was thinking of two loops one nested into the other, but maybe it's a well known problem and has a commonly understandable solution...
What if the number of Collection objects raises above two?
EDIT after Joseph Daigle comment: The items of the Collection objects are all of the same type, they are rooms of hotels found to be bookable under certain conditions.
Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();
for(Room roomA : roomsFromA){
for(Room roomB : roomsFromB){
//add roomA and roomB to something, this is not important for what I need
//the important part is how you handle the part before
//especially if Collection objects number grows beyond two
}
}
EDIT 2: I'll try to explain better, sorry for the question being unclear.
Follows an example:
A user requests for a double and a single room.
The hotel has 3 double and 4 single rooms available.
I need to associate every "double room" to every "single room", this is because each Room has its own peculiarity say internet, a more pleasant view, and so on. So i need to give the user all the combinations to let him choose.
This is the simple case, in which only two Collection of Room objects are involved, how do you manage the problem when say both hotel and user can offer / request more Room types?
What you are trying to do here is to get all possible permutations of choosing X from a set of Y. This is a well known problem in discrete mathematics and I think it is just called Combinatorial Mathematics.
To solve your problem you need to create a super collection containing all your Room types. If this is an array or a List you can then use this example to calculate all possible ways of choosing X from the set of Y. The example will give you the indices from the list/array.
Do the collections line up exactly?
HashMap map = new HashMap();
for (int i=0; i<c1.Size(); i++) {
map.put(c1[i], c2[i]);
}
Well, since I don't know if you will need to search for both of them having only one, the HashMap won't work.
I would create a class that receives a Pair.. sort of:
private static class Pair<K, T> {
private K one;
private T two;
public Pair(K one, T two) {
this.one = one;
this.two = two;
}
/**
* #return the one
*/
public K getOne() {
return one;
}
/**
* #return the two
*/
public T getTwo() {
return two;
}
}
And create a List with them.
Your example implies that the return value from "roomsFromB" is a subcollection of the return value of "roomsFromA", so it'd be more natural to model it that way:
class Room {
public Collection<Room> getRoomsFromB { ...
}
which would then let you do :
//Collection rooms
for (Room a: rooms)
{
for(Room b a.getRoomsFromB){ ...
This is assuming that they're modeled hierarchically, of course. If they're not then this is inappropriate, but then the question you're asking, it seems to me, is really how to model the relationship between them, and you haven't yet made that explicit.
You might reconsider whether you need exactly this logic. You're introducing an O(n^2) operation, which can quickly get out of hand. (Technically O(mn), but I'm guessing m and n are roughly the same order.)
Is there another solution to your problem? Perhaps you could create a 'set' which includes all of A and all of B, and then each object in A and B could point to this set, instead?
I assume that:
Each element in collection 1 will
match a single element in
collection 2
The collections have the same
size
The collections can be ordered and
the order matches each element in
both collections
Order both collections (in the same
order) by the property that
identifies each object.
Iterate through both collections with a single loop, build a relation object and add it into a new collection.
See if this helps you:
public static class Room {
private int number;
private String name;
public Room(int number, String name) {
super();
this.number = number;
this.name = name;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
}
public static class RoomRelation {
private Room a;
private Room b;
public RoomRelation(Room a, Room b) {
super();
this.a = a;
this.b = b;
}
public Room getA() {
return a;
}
public Room getB() {
return b;
}
#Override
public String toString() {
return a.getName() + "(" + a.getNumber() + ") " + b.getName() + "(" + b.getNumber() + ")";
}
}
public static void main(String[] args) {
List<Room> roomsFromA = new ArrayList<Room>();
List<Room> roomsFromB = new ArrayList<Room>();
roomsFromA.add(new Room(1,"Room A"));
roomsFromA.add(new Room(2,"Room A"));
roomsFromB.add(new Room(1,"Room B"));
roomsFromB.add(new Room(2,"Room B"));
Comparator<Room> c = new Comparator<Room>() {
#Override
public int compare(Room o1, Room o2) {
return o1.getNumber() - o2.getNumber();
} };
Collections.sort(roomsFromA, c);
Collections.sort(roomsFromB, c);
List<RoomRelation> relations = new ArrayList<RoomRelation>();
for (int i = 0; i < roomsFromA.size(); i++) {
relations.add(new RoomRelation(roomsFromA.get(i), roomsFromB.get(i)));
}
for (RoomRelation roomRelation : relations) {
System.out.println(roomRelation);
}
}
Your question is quite unclear. As I understand you want to list all combinations of rooms, minus duplicates. Here us some code to build up a 2d array of all the room combinations. For more kinds of room, put in another nested loop.
Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();
Room[][] combinations = new Room[roomsFromA .size()][roomsFromB .size()];
int a = 0;
int b = 0;
for(Room roomA : roomsFromA){
for(Room roomB : roomsFromB){
combinations [a][b] = [roomA][roomB]; //Build up array
b++;
}
a++;
}
return combinations;
It is a common problem. It's called a Cartesian product. If you have two collections like in your case, I would not hesitate to have two nested loops. Otherwise, see this question.