I am trying to loop around the value that already got populated in Registration class. I have already put a breakpoint in getInstance() method in Registration class. When the cursor reaches the below for loop code.
for (final Registration.HolderEntry entry : Registration.getInstance()) {
// do other things..
}
I do a F5 on that. And then it gooes to getInstance() method of Registration class (below is the class). And when I inspect on instance variable at that point, I always see values populated in listOfBundles list which is good.
But if I keep on pressing F5 again, at some point it comes to iterator method in Registration class and then if I inspect on listOfBundles list, I don't see any values in that list which is what I am not able to understand why it is happening like this. No other code is running which might change the value of listOfBundles.
public class Registration implements Iterable<Registration.HolderEntry> {
private List<String> listOfBundles = new LinkedList<String>();
private final Map<String, HolderEntry> bundleMapper = new HashMap<String, HolderEntry>();
private Registration() {
//
}
private static class BundlesHolder {
static final Registration instance = new Registration();
}
public static Registration getInstance() {
return BundlesHolder.instance;
}
public synchronized void registerBundles(final String bundleName, final IBundleCollection collection) {
HolderEntry bundleHolder = new HolderEntry(bundleName, collection);
bundleMapper.put(bundleName, bundleHolder);
listOfBundles.add(bundleName);
}
#Override
public synchronized Iterator<HolderEntry> iterator() {
List<String> lst = new LinkedList<String>(listOfBundles);
List<HolderEntry> list = new LinkedList<HolderEntry>();
for (String clName : lst) {
if (bundleMapper.containsKey(clName)) {
list.add(bundleMapper.get(clName));
}
}
Collections.reverse(list);
return list.iterator();
}
// some other code
}
I hope the question is clear enough. Can anybody tell me what wrong I am going here?
because you use static instance always return same object from
public static Registration getInstance()
method. (only one time Registration is initialize).
there are no different object is your iteration. same object is iterating on your iteration. its not like applying to every object changes you make while iterate but it is same object you iterate and change values.
I dont know your real requirement. but try to use this.
public static Registration getInstance() {
return new Registration();;
}
Related
I want to create a list, add blocks to it and then use it in a BlockBreakEvent to check if the block is in the list and cancel the event if it's not. But I can't seem to create and add things in it any other way than in the actual event itself (which looks to me like it would create issues). The only thing that is working for me is creating the list in the event and adding blocks to it one by one which looks really messy compared to: creating the list in a separate class and just checking the list with if(Listname.contains(block)) does anyone know how I can achieve this? Whether its dependency injection, or whatever else. I just can't figure out how to put it to use.
Here's what I've tried and is currently working for me, but I believe it's theoretically incorrect:
public class Event implements Listener {
#EventHandler
public void onBreak(BlockBreakEvent e) {
List<Material> allowedblocks = new ArrayList<Material>();
allowedblocks.add(Material.STONE);
//repeat this 10-50 times for whatever item
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedblocks.contains(block)){
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}else{
p.sendMessage("Valid Block");
}
}
}
You can make allowedBlocks List a class field and fill it with elements inside of the constructor.
public class YourClass {
private List<Material> allowedBlocks = new ArrayList<>();
public YourClass() {
allowedBlocks.add(Material.STONE);
//repeat this 10-50 times for whatever item
}
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedBlocks.contains(block)){
p.sendMessage("Valid Block");
} else {
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}
}
}
Another approach would be to make the list static and fill it with values inside of a static block. I would not recommend making the list static if you are planning to change its values, but if your allowed blocks are going to remain the same, it may be a good idea to even go further and make it public, so you can access it from anywhere without an instance of YourClass
public class YourClass {
public static final List<Material> allowedBlocks;
static {
List<Materials> list = new ArrayList<>();
list.add(Material.STONE);
//repeat this 10-50 times for whatever item
//use an unmodifiable list,
//so you do not accidentally change its content later
allowedBlocks = Collections.unmodifiableList(list);
}
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedBlocks.contains(block)){
p.sendMessage("Valid Block");
} else {
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}
}
}
In the first case, there will be a list of allowedBlocks per instance of YourClass, which means, that every time you call new YourClass() a new List will be created and filled. In the second case, there will be only one list which will be created and populated on class loading (at the very beginning of the program) start up.
P.S. I would rather use a Set instead of a List here, considering you are using contains very often.
Since you are using an enum to store your Material types, you can simply call the static .values() method through Material.
Ex:
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(List.of(Material.values()).contains(block)){
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}else{
p.sendMessage("Valid Block");
}
}
}
If you need to be able to customize what values are in the List you can use the singleton pattern to access that information globally.
The instance can be accessed statically from anywhere in the application:
import java.util.List;
public class BlockController {
public static BlockController instance = new BlockController();
private List<Material> allowedBlocks;
public BlockController() {
this.allowedBlocks = new ArrayList<>();
}
public void addAllowedBlock(Material mat) {
this.allowedBlocks.add(mat);
}
public void removeAllowedBlock(Material mat) {
this.allowedBlocks.remove(mat);
}
public boolean containsBlock(Material mat) {
return this.allowedBlocks.contains(mat);
}
public void clear() {
this.allowedBlocks.clear();
}
/**
* You can add more functionality here...
* This class can be accessed anywhere in the application
*
* use:
*
* BlockController controller = BlockController.instance;
* controller.containsBlock(Material.BLOCK);
*/
}
One approach to creating the list in a separate class is to use a static initializer block:
public class MyClass {
public static final List<Material> ALLOWED_MATERIALS = new ArrayList<>();
static {
ALLOWED_MATERIALS.add( Material.STONE );
}
public static List<Material> getAllowedMaterials() {
return Collections.unmodifiableList( ALLOWED_MATERIALS );
}
...
}
Try to create the List in a static context. This way the list is the same for all instances:
public class MyClass {
public static List<Material> allowedblocks = new ArrayList<Material>();
#EventHandler
public void onBreak(BlockBreakEvent e) {
allowedblocks.add(Material.STONE);
...
Then you can call the List from everywhere like this (e.g. if statement):
if(MyClass.allowedblocks.contains(block))
Your problem seems similar to this question, maybe this answer helps too: .
In a Android application I am making I have an array of instances of a certain class I made, and later in the program I need to use the getter and setter methods from that class on an instance of the class from the array. Do I need to assign the instance of the class from the array to a new class initializer? Here is some code to clear this up:
Class
public class ProfileInformation {
private String console;
private String gamertag;
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getGamertag() {
return gamertag;
}
public void setGamertag(String gamertag) {
this.gamertag = gamertag;
}
}
Array
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
Some instances of ProfileInformation are then added to arraylist, and then I get one of the instances from the arraylist and try to use getGamertag() to set it to a string:
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
The problem is example will equal null. Why is this?
First, an Arraylist is a List, try not to confuse that with actual arrays.
Do I need to assign the instance of the class from the array to a new class initializer?
You don't need to get an element out of the Arraylist, no. You can chain many methods together
String example = ProfTags.get(ProfTags.size()-1).getGamertag();
example will equal null. Why is this?
For the same reason any object is null... You never set it equal to anything else
This code runs on my laptop:
public static void main(String[] args) {
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
element = new ProfileInformation();
element.setGamertag("Actual Gamer tag value");
ProfTags.add(element);
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
}
Output is:
Actual Gamer tag value
I guess you didn't call setGamertag(String).
I was asked to demonstrate a Singleton class design for my assignment. The version I submitted uses Strings and works fine, but I just can't get the reserveLane method to work properly with integers. Whenever I call the reserveLane method in the code below, it removes the element with the index of the integer passed into it instead of the element containing the value that matches the integer passed in. The program is supposed to print each message in the removeLane method once.
import java.util.*;
public class Race {
// store one instance
private static final Race INSTANCE = new Race(); // (this is the singleton)
List<Integer> lanes = new ArrayList<>();
public static Race getInstance() { // callers can get to
return INSTANCE; // the instance
}
private Race() {
lanes.add(1);
lanes.add(2);
}
public void removeLane(int lane) {
if(lanes.contains(lane)){
lanes.remove(lane);
System.out.println("Lane successfully reserved.");
} else {
System.out.println("Lane is already reserved.");
}
}
public static void main(String[] args) {
assignLane(1);
assignLane(1);
}
private static void assignLane(int lane) {
Race race = Race.getInstance();
race.removeLane(lane);
}
}
I'm wondering if I'm wasting my time trying to go this route or is there a way to fix it?
Integer integer = new Integer(lane);
lanes.remove(integer);
Your lanes is an arraylist of Integer objects, not int. Passing an int to Arraylist.remove(int index) will remove an object at that index, but if you pass an Integer object, the remove() function will delete the first occurrence of that object.
You are using primitive type to do your removal of element. You can convert it the Wrapper class and do it. Change the removeLane method as follows:
public void removeLane(Integer lane) {
if(lanes.contains(lane)){
lanes.remove(lane);
System.out.println("Lane successfully reserved.");
}
else{
System.out.println("Lane is already reserved.");
}
}
ArrayList Docs
E remove(int index)- Removes the element at the specified position in this list.
boolean remove(Object o) - Removes the first occurrence of the specified element from this list, if it is present.
As you have sent an int primitive type to method remove it has called remove(int index). Instead just send an Integer object and then it will call method remove(Object o) and it will work fine.
Working Code:
package stackoverflow;
import java.util.ArrayList;
import java.util.List;
public class Race {
private static final Race INSTANCE // store one instance
= new Race(); // (this is the singleton)
List<Integer> lanes = new ArrayList<>();
public static Race getInstance() { // callers can get to
return INSTANCE; // the instance
}
private Race() {
lanes.add(1);
lanes.add(2);
}
public void removeLane(int lane) {
if (lanes.contains(lane)) {
lanes.remove((Integer) lane);
System.out.println("Lane successfully reserved.");
} else {
System.out.println("Lane is already reserved.");
}
}
public static void main(String[] args) {
assignLane(1);
assignLane(1);
}
private static void assignLane(int lane) {
Race race = Race.getInstance();
race.removeLane(lane);
}
}
I have been trying to access the arrayList from another file. However when i was running the size it was returning 0.
However running it on the class it is on would return a value. It seems that i can't access it from another class and that i am accessing it wrongly.
public void test()
{
ArrayList<Events> eventArrayList = ( new ReadFile()).getList();
System.out.println(eventArrayList.size());
}
public class ReadFile
{
//Event arraylist
public ArrayList<Events> eventArrayList = new ArrayList<Events>();
System.out.println(eventArrayList.get(0).events);
public ArrayList<Events> getList()
{
ArrayList<Events> eventArrayList = new ArrayList<Events>();
return eventArrayList;
}
}
You are "resetting" the list every time you call getList(). Remove the first line of code.
public ArrayList<Events> getList() {
return eventArrayList;
}
Moreover, you should return List<Events> (you don't need to reveal the implementation used) and you shouldn't return the list but a copy of the list if you don't want other objects to change it (remember that it is passed by reference so if you change it, you will change it everywhere).
I've defined the following enum in Groovy, though for the purpose of this question it could be Java code:
enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static Set<String> allSearchTokens = new HashSet<String>();
FestivalType() {
String searchToken = this.name().tokenize('_').first().toLowerCase();
if (searchToken in allSearchTokens) {
throw new RuntimeException("Duplicate search token");
} else {
this.searchToken = searchToken;
allSearchTokens.add(searchToken);
}
}
final String searchToken;
}
What I'm trying to do in the constructor is establish whether the first token in the name of each enum constant is unique, where _ is used as the token separator.
However, this code doesn't work because allSearchTokens is not initialized until after all the constants are instantiated, so I get a NullPointerException here
allSearchTokens.add(searchToken)
You can work around this as follows:
public enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static class SetHolder {
static Set<String> allSearchTokens = new HashSet<String>();
}
final String searchToken;
FestivalType() {
String searchToken = name().split("_")[0].toLowerCase();
if (SetHolder.allSearchTokens.contains(searchToken))
throw new RuntimeException("Duplicate search token");
this.searchToken = searchToken;
SetHolder.allSearchTokens.add(searchToken);
}
}
This compiles because of the java specification that all static initializers must be completed before the class is used. By making the Set a static field of a sttic inner class, you guarantee that it will be initialized before the first enum is constructed.
Also, I took the liberty of changing/fixing a few things in your code:
Use a Set rather than a List: Values are unique
Use split(): There is not such method tokenize() for String in java
Remove else: After a return or throws, else is always redundant because execution of the block is halted by these keywords (there is no "else" to handle)
As an aside, this technique is also great for lazy initialization of singletons:
public class MyLazySingleton() {
private static class InstanceHolder {
static MyLazySingleton INSTANCE = new MyLazySingleton();
}
public static MyLazySingleton getInstance() {
return InstanceHolder.INSTANCE;
}
}
The INSTANCE field is only constructed when the getInstance() method is first called!
Look mom! Lazy initialization without locks, without null checks, without synchronization of any kind and 100% bulletproof! (Object deserialization hacks notwithstanding)
It's magic :)
I have done something similar and the following has worked for me:
enum MyEnum{
Enum1, Enum2;
private static List<String> myList;
private static void addToList(MyEnum enum){
if(myList == null){
myList = new ArrayList<String>();
}
myList.add(enum.name());
}
private MyEnum(){
addToList(this);
}
}