I have a simple Class with a inner class.
I want to set the following:
users[0][user_id]=8
users[1][user_id]=25
This is class:
public class ChatRequest {
private List<Userbean> users;
public List<Userbean> getUsers() {
return users;
}
public void setUsers(List<Userbean> users) {
this.users = users;
}
public static class Userbean {
private int user_id;
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
}
I tried it but without success.
How can I set the user id of the first user to 8 and the user id of the second user to 25?
These are java basic. Before refer to the Android SDK or something else please take a look into a java learning book/page.
However. Your "models" (or simple classes) are correct. To use these classes (and set the IDs you want) you need some instance of a UserBean first.
final ChatRequest.Userbean user0 = new ChatRequest.Userbean()
final ChatRequest.Userbean user1 = new ChatRequest.Userbean()
Then you can set the ID to it:
user0.setUser_id(8);
user1.setUser_id(25);
To finally add these users to the ChatRequest you need a instance of that as well:
final ChatRequest chatRequest = new ChatRequest();
Adding the users a simple call like that:
chatRequest.setUsers(Arrays.asList(user0, user1));
To be clear. These are the basic to create instances and set some values to classes/"models".
I think to answer your question we need some "preconditions". We assume that "someone" have already create some users and set it to the ChatRequest object which you receive in a "callback". To change some properties from the Userbean values can done in following way:
#Override
public void onChatRequestCreated(ChatRequest request) {
request.getUsers().get(0).setUser_id(8);
request.getUsers().get(1).setUser_id(25);
}
To set these values you should use this code:
users.get(0).setUser_id(8);
users.get(1).setUser_id(25);
Related
Q: I have a Bank class containing multiple loan accounts (LoanAccount class). I've create a LoanAccountService that have the CRUD functionalities. My concerns are about how I implemented the update functionality.
Bank
public class Bank {
private List<LoanAccount> loanAccounts;
}
Loan account
public class LoanAccount {
private String id;
private Integer numberOfInstallments;
private LoanAccountType type;
private Date creationDate;
private BigDecimal loanAmount;
}
Service
public class LoanAccountService{
private Bank bank;
public LoanAccountService(Bank bank) {
this.bank = bank;
}
public LoanAccount update(LoanAccount loanAccount) {
Optional<LoanAccount> account = bank.getLoanAccounts()
.stream()
.filter(la -> la.getId().equals(loanAccount.getId()))
.findAny();
if (account.isPresent()) {
account.get().setCreationDate(loanAccount.getCreationDate());
account.get().setLoanAmount(loanAccount.getLoanAmount());
account.get().setNumberOfInstallments(loanAccount.getNumberOfInstallments());
account.get().setType(loanAccount.getType());
} else {
throw new IllegalArgumentException("The object does not exist.");
}
return loanAccount;
}
}
When the method update is called with a LoanAccount containing an id that already exists in loanAccounts list, I want to update the existing object with the object loanAccount given as parameter.
Above is my implementation, but I feel like there should be better ways to do it.
Use Builder for getter and setter
public class LoanAccount {
private String id;
private Integer numberOfInstallments;
// add other properties
public String getId() {
return id;
}
public LoanAccount setId(String id) {
this.id = id;
return this;
}
public Integer getNumberOfInstallments() {
return numberOfInstallments;
}
public LoanAccount setNumberOfInstallments(Integer numberOfInstallments) {
this.numberOfInstallments = numberOfInstallments;
return this;
}
Use this one for update method
public LoanAccount update(LoanAccount loanAccount) {
return bank.getLoanAccounts()
.stream()
.filter(la -> la.getId().equals(loanAccount.getId()))
.findFirst().orElseThrow(IllegalArgumentException::new)
.setCreationDate(loanAccount.getCreationDate())
.setLoanAmount(loanAccount.getLoanAmount())
.setNumberOfInstallments(loanAccount.getNumberOfInstallments())
.setType(loanAccount.getType());
}
You could use a HashMap where the TKey is the type of your LoanAccount.id.
Then call loanAccounts.put(id, object)
This will update the object if there is already an Id and add a new object if not.
This is a cheap, dirty way. Another way of doing it would be to make your LoanAccount class implement Comparable and in the compareTo() method make a id based comparation.
Do the same thing overriding your equals() and you should be ready to go.
#Override
public boolean equals(object obj) {
if (obj == null) return false;
return ((LoanAccount)obj).getId() == this.getId();
}
something like that.
(code wrote by memory, can have errors and lacks validations like the data type)
What kind of persistence layer do you use?
why do you need to loop through all of the bank accounts?
Did you fetch all the accounts from the repository and loop over the service layer? If so why?
why not you fetch the corresponding single record from repository and update?
Why not you use to find and update the records instead of using the above points?
These questions may give you an idea. If you answering it !!!
If not let we discuss deeper
I have enum class that describes possible tickets types and have custom atribute to keep ticketId. When I try to add some tickets to ArrayList it makes all tickets of type X have the same ticketId. Why is that and what's more important how can I solve it?
Simplified enum class:
public enum Ticket {
FirstClass(0),
PremiumClass(1),
EconomyClass(2);
private int elementId;
private Long ticketId;
Ticket(int elementId) {
this.elementId=elementId;
}
public Long getTicketId() {
return ticketId;
}
public void setTicketId(Long ticketId) {
this.ticketId = ticketId;
}
}
Simplified method:
public void myMethod() {
ArrayList<Ticket> tickets = new ArrayList<>();
Ticket ticket = Ticket.FirstClass;
ticket.setTicketId(1L);
tickets.add(ticket);
ticket = Ticket.FirstClass;
ticket.setTicketId(2L);
tickets.add(ticket);
}
It is happening because there is only one instance for every enum constant. Calling Ticket.FirstClass will fetch the same instance every time. So you are adding the same object to the list twice.
There is really only one instance of Ticket.FirstClass, and there will only ever be one instance.
What you really have isn't a Ticket, but a TicketType. You should have a separate class for Ticket.
FirstClass is an instance of Ticket so when you're calling it, it's always the same one, you take the reference to the same object.
What you would need is a model with a Ticket and a TicketType
enum TicketType {
FirstClass,
PremiumClass,
EconomyClass
}
class Ticket {
private TicketType type;
private Long ticketId;
Ticket(TicketType type, long ticketId) {
this.type = type;
this.ticketId = ticketId;
}
}
// ---------------------------------------------------------
// And
public void myMethod() {
ArrayList<Ticket> tickets = new ArrayList<>();
Ticket ticket = new Ticket(TicketType.FirstClass, 1L);
tickets.add(ticket);
ticket = new Ticket(TicketType.FirstClass, 2L);
tickets.add(ticket);
}
Don't use enums for dynamic values,see sonar's "enum" fields should not be publicly mutable
enums are generally thought of as constant, but an enum with a public field or public setter is not only non-constant, but also vulnerable to malicious code.
See example of making enum dynamic by making it implement an interface
Nothing different from other answers, just to add some colors.
When you obtain firstClass you actually are getting same object, and adding that again.
Each enum value (you have got three) exists only once and each time you are using one of them you are just reusing one of those three values by creating a reference, there are no copies.
This means if you change the ticketId on the FirstClass value, it is changed wherever that value is referenced.
It seems you want to model a little ticket system. Each object having an own identity should be modeled as a class which has a property for the type and the id:
public class Ticket {
private Long ticketId;
private TicketType type;
public Long getTicketId() {
return ticketId;
}
public void setTicketId(Long ticketId) {
this.ticketId = ticketId;
}
public TicketType getType() {
return type;
}
public void setType(TicketType type) {
this.type = type;
}
}
public enum TicketType {
FirstClass(0),
PremiumClass(1),
EconomyClass(2);
private final int elementId;
Ticket(int elementId) {
this.elementId = elementId;
}
public int getElementId() {
return elementId;
}
}
Then you can use it this way:
public void myMethod() {
ArrayList<Ticket> tickets = new ArrayList<>();
Ticket ticket = new Ticket();
ticket.setType(TicketType.FirstClass);
ticket.setTicketId(1L);
tickets.add(ticket);
ticket = new Ticket();
ticket.setType(TicketType.FirstClass);
ticket.setTicketId(2L);
tickets.add(ticket);
}
I don't know why you need an elementId on the ticket type, that's why I just left it there (without using it). Probably you should rename ticketId to just id to keep it simple.
If the ticket's type or ticketId are never changed after assigning them you may want to remove the setters and assign the values in the constructor of Ticket (and make the attributes final).
Even if it's ok that they are changeable, you may introduce such a constructor to have code which is better readable:
In Ticket.java:
public Ticket(Long ticketId, TicketType type) {
this.ticketId = ticketId;
this.type = type;
}
Then you can write:
tickets.add(new Ticket(1L, TicketType.FirstClass));
If ticket is a persisted entity (which gets inspected by a framework like Hibernate) you might have to keep a no-args constructor to make it instantiable when loading it from a database.
I'm implementing the "auto-increment" id using strategy described here:
http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
Basically the value of the seqId field is set by calling an utility function that updates the counter on an auxiliary collection and returns the incremented value. Sounds great.
My issue is in mapping this to be used with Morphia. The tutorial suggests performing the insert (such as in the shell) like so:
db.users.insert(
{
seqId: getNextSequence("userid"),
name: "Sarah C."
}
I'm basically looking to do something like setting the POJO seqId field to something that Morphia will translate into an insert like the one above when I invoke save().
My POJO looks like this:
#Entity
public class User {
#Id
private Long id;
// THIS IS THE FIELD I WANT TO AUTO-INCREMENT
private Long seqId;
private String name;
...
}
The question is: How to make Morphia set the value of a field as the value returned by a function call?
I looked into using the #PrePresist annotation to perform this function call and getting the value, then setting it in the +_id field. That has several drawbacks such as making multiple calls to MongoDB instead of just one, and also the fact that my model objects don't have a reference to the datastore and I'd rather not mix up the concerns.
Is this possible? Any suggestions?
I'm on MongoDB 2.6.6 using the latest Java drivers.
Thanks!
PS: I'm aware that auto-increment is not recommended in large environments. I need it anyways for this specific scenario.
I'll describe the solution that's working for us quite well. Note that this supports auto increments on the class level and a subset of it — so you can count users or admin-users (user with an admin enum or whatever).
This contains the current value for each auto increment field, it's basically a reference:
#Entity(noClassnameStored = true)
public class AutoIncrementEntity {
#Id
protected String key;
protected Long value = 1L;
protected AutoIncrementEntity() {
super();
}
/**
* Set the key name — class or class with some other attribute(s).
*/
public AutoIncrementEntity(final String key) {
this.key = key;
}
/**
* Set the key name and initialize the value so it won't start at 1.
*/
public AutoIncrementEntity(final String key, final Long startValue) {
this(key);
value = startValue;
}
public Long getValue() {
return value;
}
}
In your persistence service, you could use the following to set / create the auto increment automatically:
public <E extends BaseEntity> ObjectId persist(E entity) {
// If it's a user and doesn't yet have an ID, set one; start counting from 1000.
if ((entity instanceof UserEntity) && (((UserEntity) entity).getUserId() == null)) {
((UserEntity) entity).setUserId(
generateAutoIncrement(entity.getClass().getName(), 1000L));
}
// Additionally, set an ID within each user group; start counting from 1.
if ((entity instanceof UserEntity) && (((UserEntity) entity).getRoleId() == null)) {
((UserEntity) entity).setRoleId(
generateAutoIncrement(entity.getClass().getName() + "-" + entity.getRole(), 1L));
}
mongoDataStore.save(entity);
return entity.getId();
}
/**
* Return a unique numeric value for the given key.
* The minimum value, set to 1 if nothing specific is required.
*/
protected long generateAutoIncrement(final String key, final long minimumValue){
// Get the given key from the auto increment entity and try to increment it.
final Query<AutoIncrementEntity> query = mongoDataStore.find(
AutoIncrementEntity.class).field("_id").equal(key);
final UpdateOperations<AutoIncrementEntity> update = mongoDataStore
.createUpdateOperations(AutoIncrementEntity.class).inc("value");
AutoIncrementEntity autoIncrement = mongoDataStore.findAndModify(query, update);
// If none is found, we need to create one for the given key.
if (autoIncrement == null) {
autoIncrement = new AutoIncrementEntity(key, minimumValue);
mongoDataStore.save(autoIncrement);
}
return autoIncrement.getValue();
}
And finally your entity:
#Entity(value = "user", noClassnameStored = true)
public class UserEntity extends BaseEntity {
public static enum Role {
ADMIN, USER,
}
private Role role;
#Indexed(unique = true)
private Long userId;
private Long roleId;
// Role setter and getter
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
}
There's nothing specific going on in the entity. All the logic is handled by the persistence service. I'm not using the #PrePersist, because you'd then need to put the persistence service into the entity, which doesn't sound like a good idea.
I have two Classes.
one DAO that has an Arrraylist of Users (user is instace of User class)
and one method in another class that checks if there is a user with our input name or not
How can I use Hashmap (usernames, User) instead of Arraylist of Users?
public class UserDAO {
private static UserDAO instance;
private static String fileName = "sources/users.aaa";
//--------------------------------------------------------
private UserDAO(){
}
//--------------------------------------------------------
public boolean storeUsers(ArrayList<User> Users){
return IOFile.writeObject(Users, fileName);
}
//--------------------------------------------------------
public ArrayList<User> getUsers(){
ArrayList<User> Users = (ArrayList<User>) IOFile.readObject(fileName);
return Users;
}
//--------------------------------------------------------
public static UserDAO getInstance(){
if(instance == null)
instance = new UserDAO();
return instance;
}
}
and one method in another class that checks if there is a user with our input name or not:
User user = new User(firstName, lastName, userName, password);
ArrayList<User> users = UserDAO.getInstance().getUsers();
for (User user2 : users) {
if (user.equals(user2)){
system.out.println ("Error!!");
return;
}
}
users.add(user);
UserDAO.getInstance().storeUsers(users);
In this case, since you're just trying to check if the user exists, you could use a HashSet. A set has constant time lookups. So instead of your loop, it would just be users.contains(user).
You could use a map if you were looking up by something other than the actual User object, e.g. a mapping of names to users.
In either case, if you're using collection where you're checking contains, you must implement both equals and hashCode properly.
How would you go about creating a class like this:
public class tmUser {
private String Username;
private int wHours;
static int numUsers;
public tmUser(){
Username = "";
wHours = 0;
}
public tmUser(String U, int H){
Username = U;
wHours = H;
}
public void setUsername(String U){
Username = U;
}
public void setwHours(int H){
wHours = H;
}
public String getUsername(){
return Username;
}
public int getwHours(){
return wHours;
}
public static void initnumUsers(){
numUsers = 0;
}
public static int getnumUsers(){
return numUsers;
}
}
and then printing all of tmUser instances Username variable? in maybe a for each loop? I'm hoping for something like:
for each(tmUser){
System.out.println(Username);
}
This is for a menu in a program which displays all created users usernames.
You almost had it:
List<TmUser> tmUsers = ...
for(TmUser user : tmUsers) {
System.out.println(user.getUsername());
}
You would also want to capitalize tmUser into TmUser.
When you create a tmUser add it to a collection like
List<TmUser> tmUsers = new ArrayList<TmUser>();
TmUser tmUser = new TmUser(username, hoursWorked);
tmUser.add(tmUser);
// later
for(TmUser tmUser: tumUsers)
System.out.println(tmUser.getUsername());
You need to store all of tmUser instances somewhere first. You could do it this way:
public class tmUser {
...
public static List<tmUser> USERS = new ArrayList<tmUser>();
public tmUser() {
...
USERS.add( this );
}
and then printing:
for (tmUser user : tmUser.USERS) {
System.out.println(user.getUsername());
}
The 3 current answers are basically the same. Just wanted to add that if the class defined a toString() that returned the user name, it would not be necessary to add the .getUsername() method call, since System.out.println(Object) will automatically call the toString() method.
Whether this could work for your use case is debatable. The toString() method would normally provide more data on the object.
As the answers already posted indicate, this would involve maintaining some sort of data structure that holds references to all instances of tmUser (e.g. a List<tmUser>).
This would mean that a reference to each and every instance ever created will always be held there, they will never be garbage collected. You could explicitly remove them when you decide an instance is no longer needed, but then you would have to keep track of the life cycle of all instances, and basically end up doing memory management yourself.