How to put 2 arraylists into one hashmap? - java

So I'm making a plugin and I want to put two ArrayList (of two different teams) to one Hashmap, so I can get both of the teams in this method:
public static Teams getTeam(Player player) {
if (!hasTeam(player))
return null;
return zombiesTeam.get(player) && survivorsTeam.get(player);
}
Here is the two ArrayList and a Hashmap that I want to have:
public static HashMap<zombiesTeam, survivorsTeam> playerTeams = new HashMap<zombiesTeam, survivorsTeam>();
public static ArrayList<Player> zombiesTeam = new ArrayList<Player>();
public static ArrayList<Player> survivorsTeam = new ArrayList<Player>();
P.S. I know that this code isn't correct
Please ask me for any further additional information
Thanks in advance.

You should do something like this:
public static HashMap<String, ArrayList<Player>> playerTeams = new HashMap<>();
playerTeams.put("zombies", zombiesTeam);
playerTeams.put("survivors", survivorsTeam );

If you want to represent all your "teams" by a hashmap from the team name to the list of team members, I would suggest this:
// In the same class where zombiesTeam and survivorsTeam are declared
public static Map<String, List<Player>> getTeamsByName() {
Map<String, List<Player>> teamsByName = new HashMap<>();
teamsByName.put("zombiesTeam", zombiesTeam);
teamsByName.put("survivors", survivorsTeam);
return teamsByName;
}
However, be sure that you need to use static fields and methods. Your model doesn't suggest this.
For instance, you could rather declare a Team class and a Player class. Since you already have the Player class, here is how I would make the Team class:
public class Team {
private String name;
private Set<Player> teamMembers = new HashSet<>();
public Team(String name) {
this.name = name;
}
public String getName() {
return this.teamName;
}
public Set<Player> getTeamMembers() {
return this.teamMembers;
}
public addPlayer(Player player) {
this.teamMembers.add(player);
}
public removePlayer(Player player) {
this.teamMembers.remove(player);
}
public reset() {
this.teamMembers.clear();
}
}
Be sure to override equals and hashcode for HashSet and HashMap to work correctly. More information about this here:https://www.geeksforgeeks.org/equals-hashcode-methods-java/

Related

Java: How do I initialize an array with objects of a class at the time of object creation?

I'm working on a code and I want to return the ranking board of the teams in the championship.
I want to make an ArrayList that contain the objects of a class name Team, so I can return the whole ranking board with all the teams .
I want it done at the time of object creation and in this respect I have the following code that is not working:
// the constructor
public Team(String name) {
this.name = name;
teams.add(this);
}
public List<Team<T>> teams = new ArrayList<>();
I have also tried to initialised teams inside a method in which I add the players:
public boolean addMembers(T player) {
if (members.contains(player)) {
System.out.println("Player already in the list");
return false;
} else {
members.add(player);
teams.add(this);
System.out.println(player.getName() + " has been picked for team " + this.name);
returnClassament();
return true;
}
}
this way may be helpful if I did not misunderstand you
public Team(String name, List<Team> list) {
this.name = name;
if(list != null) list.add(this);
}
import java.util.ArrayList;
public class Team{
//we create private variables here because only the constructor is accessing them
private String name;
private int score;
//create a static ArrayList that holds type of class Team here so all objects refer to one and it is not copied over to each object (as per i've learned because static is confusing)
public static ArrayList<Team> teams=new ArrayList<Team>();
public Team(String name,int score){
this.name=name;
this.score=score;
//tell the program that the instance variable has the same value as the parameter
teams.add(this);
//adding the object to the ArrayList
}
//This is not necessary; it just prints the values of each object in the ArrayList
public void printTeamStats(){
System.out.println(name+" "+score);
}
}
The AddPlayer method of the Championship class can be used to add a player to the system
Void addPlayer (String surname, Strong country, integer age, String position) {

Trying to store Bukkit ItemStack field to a file but ItemStack is not Serrializable

ItemStack is not serializable and I'm trying to save an object called Objective with an ItemStack field to a file but since ItemStack is not serializable this does not work. I tried extending ItemStack and implementing Serializable and changing the field to my new serializable sub class but this also did not work. Here are the relevant parts of my original code:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import org.bukkit.inventory.ItemStack;
public class Objective implements Serializable {
private static final long serialVersionUID = -2018456670240873538L;
private static ArrayList<Requirement> requirements = new ArrayList<>();
private String name;
private Requirement requirement;
private ItemStack reward;
private int tillComplete;
private boolean complete;
public Objective(String name, int requirementIndex, int tillComplete, ItemStack reward) {
if(requirements.isEmpty()) {
requirements.add(Requirement.kill_Skeletons);
requirements.add(Requirement.kill_Spiders);
requirements.add(Requirement.kill_Zombies);
}
this.name = name;
this.requirement = requirements.get(requirementIndex);
this.tillComplete = tillComplete;
this.reward = reward;
complete = false;
}
public String getName() {
return name;
}
public Object getRequirement() {
return requirement;
}
public static ArrayList<Requirement> getRequirements() {
return requirements;
}
public static void setRequirements(ArrayList<Requirement> requirements) {
Objective.requirements = requirements;
}
public int getTillComplete() {
return tillComplete;
}
public void setTillComplete(int tillComplete) {
this.tillComplete = tillComplete;
}
public void setName(String name) {
this.name = name;
}
public void setRequirement(Requirement requirement) {
this.requirement = requirement;
}
public void setReward(ItemStackSerializable reward) {
this.reward = reward;
}
public void setComplete(boolean complete) {
this.complete = complete;
}
public ItemStack getReward() {
return reward;
}
public boolean isComplete() {
return complete;
}
}
Elsewhere in my code this line of code:
ItemStack reward = new ItemStack(Material.DIAMOND_SWORD);
Objective objective = new Objective(args[1] ,Integer.parseInt(args[2]), Integer.parseInt(args[3]), reward);
is giving me this error:
java.io.NotSerializableException: org.bukkit.inventory.ItemStack
How can I serialize this object? I need to store it but Java wont let me. Thanks for your help. If you need anymore code snippets or other information please let me know.
This is most likely an XY problem. ItemStack is not serializable, as it represents an actual stack of items at runtime. This would not make sense to store in a file. It might be worth looking at the ConfigurationSerializable interface, which is implemented by ItemStack, but I don't think you need that here.
In your example, the ItemStack that you are trying to serialize doesn't have any metadata. It is a single diamond sword. If all your rewards are just a single item, all you need to save is the Material and you can create a new ItemStack from that Material every time you want to give a player a reward. Since Material is an enum, it is serializable by default.
You could also serialize an int for stack size if some of your rewards require a stack of multiple items. If you need any metadata, serialize the data needed to construct that at runtime. For example, to give an item lore, you would store a List<String> (with a serializable implementation of List).

How to enable enum inheritance

I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}

return multiple value from one method

I have a class UserFunction and it have two method getAudioFunction and getPromptFunction with returning String value, my problem is that i want to return both value in one method
how can i able to do that
UserFunction.java
public class UserFunction{
Map<String,PromptBean> promptObject=new HashMap<String,PromptBean>();
Map<String,AudioBean> audioObject = new HashMap<String,AudioBean>();
XmlReaderPrompt xrpObject=new XmlReaderPrompt();
public String getAudioFunction(String audioTag,String langMode )
{
Map<String, AudioBean> audioObject=xrpObject.load_audio(langMode);
AudioBean audioBean=(AudioBean)audioObject.get(audioTag);
String av=StringEscapeUtils.escapeXml(audioBean.getAudio());
return av;
}
public String getPromptFunction(String promptTag,String langMode )
{
Map<String, PromptBean> promptObject=xrpObject.load(langMode);
PromptBean promptBean= (PromptBean)promptObject.get(promptTag);
String pv=StringEscapeUtils.escapeXml(promptBean.getPrompt());
return pv;
}
}
You need to return an object which holds both values. You could create a class for this purpose. The class can have two getter methods for retrieving the values.
It is not possible to return more than one value from a method in java. You can set multiple value into Map or List or create a custom class and can return that object.
public Map<String,String> getAudioAndPromptFunction(String audioTag,String langMode )
{
Map<String,String> map =new HashMap();
...
map.put("audioBean",StringEscapeUtils.escapeXml(audioBean.getAudio()));
map.put("promptBean",StringEscapeUtils.escapeXml(promptBean.getPrompt());
return map;
}
or you can create a custom bean class like.
public class AudioPrompt{
private String audioBean;
private String promptBean;
...
}
public AudioPrompt getAudioAndPromptFunction(String audioTag,String langMode )
{
AudioPrompt audioPrompt =new AudioPrompt();
...
audioPrompt.set(StringEscapeUtils.escapeXml(audioBean.getAudio()));
audioPrompt.set(StringEscapeUtils.escapeXml(promptBean.getPrompt());
return audioPrompt ;
}
You'll need to return an object that includes both of the values. This could be an array with two elements, a Pair<A,B> class (which holds two generic values, typically from some pan-project utility library), or a method-specific class such as:
public class UserFunctionXmlPairing {
public final String audioBeanXml;
public final String promptBeanXml;
}
Create a new class that holds your two strings and return that.
class AudioPromptPair {
private String audio;
private String prompt;
public AudioPromptPair(String audio, String prompt) {
this.audio = audio;
this.prompt = prompt;
}
// add getters and setters
}
You can wrap all the values you wish into a single object and return that:
public class Prompts {
private Map<String, Object> prompts = new HashMap<String, Object>();
public void addPrompt(String name, Object prompt) {
this.prompts.put(name, prompt);
}
public Object getPrompt(String name) {
this.prompts.get(name);
}
}
It's even easier if your AudioBean and PromptBean have a common super class or interface.
My preference would be to lose the "Bean" in your class names. AudioPrompt and TextPrompt would be preferred.

Can I use my objects without fully populating them?

I have situation. I have to create a Sports Club system in JAVA. There should be a class your for keeping track of club name, president name and braches the club has. For each sports branch also there should be a class for keeping track of a list of players. Also each player should have a name, number, position and salary.
So, I come up with this. Three seperate classes:
public class Team
{
String clubName;
String preName;
Branch []branches;
}
public class Branch
{
Player[] players;
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
The problems are creating Branch[] in another class and same for the Player[]. Is there any simplier thing to do this? For example, I want to add info for only the club name, president name and branches of the club, in this situation, won't i have to enter players,names,salaries etc. since they are nested in each other. I hope i could be clear. For further questions you can ask.
Here's a more complete, formal example of your scenario using conventional Accessors/Mutators (getters/setters), constructors, and Lists. The main() method below illustrates how to use your classes.
public class SportsClub
{
public static void main(String[] args)
{
//Create a team without any branches
Team myTeam = new Team("Southpaws", "South");
//Create a new Branch without any players
Branch myBranch = new Branch();
//Add myBranch to myTeam
myTeam.getBranches().add(myBranch);
//Create a new player
Player myPlayer = new Player("Bob", "Center", 120, 3);
//Add myPlayer to myBranch (and therefore myTeam)
myBranch.getPlayers().add(player);
}
}
public class Team
{
private String clubName;
private String preName;
private List<Branch> branches;
public Team(String clubName, String preName)
{
this.clubName = clubName;
this.preName = preName;
branches = new ArrayList<Branch>();
}
public String getClubName() { return clubName; }
public String getPreName() { return preName; }
public List<Branch> getBranches() { return branches; }
public void setClubName(String clubName) { this.clubName = clubName; }
public void setPreName(String preName) { this.preName = preName; }
public void setBranches(List<Branch> branches) { this.branches = branches; }
}
public class Branch
{
private List<Player> players = new ArrayList<Player>();
public Branch() {}
public List<Player> getPlayers() { return players; }
public void setPlayers(List<Player> players) { this.players = players; }
}
public class Player
{
private String name;
private String pos;
private Integer salary;
private Integer number;
public Player(String name, String pos, Integer salary, Integer number)
{
this.name = name;
this.pos = pos;
this.salary = salary;
this.number = number;
}
public String getName() { return name; }
public String getPos() { return pos; }
public Integer getSalary() { return salary; }
public Integer getNumber() { return number; }
public void setName(String name) { this.name = name; }
public void setPos(String pos) { this.pos = pos; }
public void setSalary(Integer salary) { this.salary = salary; }
public void setNumber(Integer number) { this.number = number; }
}
To answer your question, yes, you can create these objects without populating the Lists with players. The SportsClub.main() above illustrates that.
I would use a List rather than an array since they're (easily) dynamically resizable, but otherwise, you're on the right track.
Think about encapsulation and visibility too. Make all those fields private and provide accessors.
You could create an empty Branch[] array (or better yet - a list) at initialization and add to it later, that way you don't have to enter all the information upon creation - same goes for Player[].
Something like:
public class Team
{
String clubName;
String preName;
private List<Branch> branches;
public Team (String club, String pre) {
clubName = club;
preName = pre;
branches = new LinkedList<Branch>();
}
public void addBranch (Branch branch) {..}
}
public class Branch
{
private List<Player> players;
public Branch () {
players = new LinkedList<Player>();
}
public void addPlayer (Player player) {..}
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
I think that's good. You should probably have methods in the classes to manage your information though--don't try to do anything serious from "Outside" these classes.
to be more specific: All your members should be private and only used/accessed from within the classes--also in general avoid setters and getters, instead ask the class to do things for you.
For example, if you wanted to know how many players were in a branch, you would call branch.countPlayers, not access the Player array to count the players from outside.
If you wanted to know how many players were in a team, you would call team.countPlayers which would call branch.countPlayers for each Branch, sum them up and return the value.
If you wanted to see which branch a player was in, you would call Team.findPlayer(playerName). Team would call branch.hasPlayer(playerName) on each branch until it returned a true, then Team would return the Branch object that returned true.
etc.
Note that this resolves your "Populated or not" issue. If you simply have methods like "hasBranch()", "addBranch()", "removeBranch()" then it doesn't matter how or when you populate the branches array since you control it all within the Team class you can change it's implementation at any time and not change a single line outside that class.
You won't have to enter anything into the players array, nor the branch[]. Provided you make the fields accessible, of have properties, you will be able to put them in however you like.
The class structure looks good to me, but a List would be better so that you don't have to worry about resizing arrays down the road.
Nothing wrong with your classes. I personally would use a strongly-typed List to store the branches and players:
public class Team
{
String clubName;
String preName;
List<Branch> branches;
}
public class Branch
{
List<Player> players;
}
Not sure of the requirement, but you'd probably want to have some kind of identifier or name for each Branch, right?
There's nothing in these classes that forces you to create new players just to instantiate a Branch. The list of Players can remain null or empty until you need them.

Categories

Resources