Can't find .get() in Arraylist - java

For some reason .get() isn't a valid method in my code. Can somebody point out the error? (Sorry for the improper object names (wasn't planning on sharing this code))
public class Summon_Tester
{
public static void main (String [] Args)
{
Summoned_Bin Bin = new Summoned_Bin();
Bin.addToBin();
System.out.println(Bin.get(0));
}
}
Summoned_Bin code
import java.util.ArrayList;
public class Summoned_Bin
{
ArrayList<Summon> Bin = new ArrayList<Summon>();
Summoned_Bin()
{
}
void addToBin()
{
Summon summoned = new Summon();
int index = 0;
while (Bin.get(index) != null)
{
index++;
}
Bin.add(index , summoned );
}
}

The Summoned_Bin isn't an ArrayList as it does not extend the ArrayList class. Rather, it contains an ArrayList. Know that this is fine, it's quite OK to enhance a class through composition and not inheritance, but just don't try to use any ArrayList methods directly on it.
You have two common solutions:
You can make it extend ArrayList, but I'm not sure that this is the best thing to do, or
You can give it public methods that allow outside classes to extract information.
For example, give it a get(...) method:
public Summon get(int index) {
return Bin.get(index);
}
Edit
As nachokk rightly suggests, you will want to learn and follow Java code conventions, as doing this will make it much easier for others to understand your code.

Related

Update a list reference inside a method

In Java we can not reassign a reference inside a method.
So the following does not work:
class SomeClass {
List<PaidOrders> paidOrders;
List<PendingOrders> pendingOrders;
List<CancelledOrders> cancelledOrders;
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist = newOrders;
}
}
But the following does work:
class SomeClass {
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist.clear();
currentOrderlist.addAll(newOrders); // <- extra linear loop
}
}
The problem is that the second example does an extra linear loop to copy from one list to the other.
Question:
I was wondering, is there some design approach so that I could neatly just replace the references instead? I.e. somehow make the first snippet work with some change in the parameters or something?
Update
After the comments I would like to clarify that the currentOrderList can be any of the paidOrders, pendingOrders, cancelledOrders.
The code for process is the same for all types.
Hm. I see two possibilities here. Either you use some wrapper object such as AtomicReference (might be a bit overpowered because of the multi-threading issues) as the argument and then just set it there or you use a consumer.
In the second case your method would look like this:
public void process(List<OrderStatus> data, Consumer<List<Orders>> target) {
List<Person> newOrders = fromOrderStatus(data);
target.accept(newOrders);
}
Then on the calling side you would implement it like this:
process(data, e-> <<targetList>> = e);
If your list will be wrapped by a different object (for example - AtomicReference), then you will be able to change it.
public static void doSomething(AtomicReference<List<Integer>> listAtomicReference){
List<Integer> newIntegers = new ArrayList<>();
listAtomicReference.set(newIntegers);
}
public static void main(String[] args) {
AtomicReference<List<Integer>> listAtomicReference = new AtomicReference<>(Arrays.asList(4));
doSomething(listAtomicReference);
System.out.println(listAtomicReference.get());
}
Output:
[]
Making a public member variable in a class.
With that being said, I wouldn't recommend walking this path.
Is premature optimization really the root of all evil?

Create instances of classes based off of a variable

I'm currently working on a project to make a simple 2d platformer in Java for uni, and the way we've been suggested to handle levels is to create an abstract level class, and then other classes implementing it for each individual level, so:
abstract class GameLevel {}
class Level1 extends GameLevel {}
class Level2 extends GameLevel {}
etc...
And then in my main class, I have a variable to keep track of the current level number, and code to move on to the next level, which essentially is:
public void goNextLevel() {
world.stop();
if (level == FINAL_LEVEL) {
// win code
} else {
level++;
world = new Level/*next level number*/();
}
}
And I was wondering if there was a way to take the variable containing the level number and add it on to the end of the class call, to save having to have a stack of if else statements.
Thanks for any help in advance
edit: The reason I'm not keen on putting all of it in one class and then using a variable in that to change the level is that each level has to have a relatively large number of entities, which each take a few lines to set up, and adding all of the levels in one file would lead to hundreds of lines of code which would be difficult to maintain
You would do so:
try {
final Class<?> clazz = Class.forName("your.package.Level" + levelInteger);
final Constructor<?> ctor = clazz.getConstructor();
final GameLevel level = (GameLevel) ctor.newInstance();
System.out.println(level.getClass().getName());
} catch (final Exception e) {
e.printStackTrace();
}
Source and explanation: https://stackoverflow.com/a/6094602/8160563
Assuming that there in only ever one object of each LevelN class, the simplest thing to do would be to store them into an array
GameLevel[] levels = new GameLevel[5];
levels[0] = new LevelOne();
levels[1] = new LevelTwo();
And then have a little helper method to retrieve them
GameLevel getNextLevel(int currentLevel) {
return levels[currentLevel];
}

How to deal with history-sensitivity?

So I have written a Java program that has a function handInExam() that may not be called twice in a row, thus the program is history-sensitive. The problem that then occurs is that I need a variable canHandInExam to check whether this method has already been called and update this variable in each method, which leads to very poor maintainability. Below is a code snippet to show the problem.
public class NotAllowedException extends Exception {
public NotAllowedException(String message) {
super(message);
}
}
import java.util.Scanner;
public class Exam {
String[] exam;
String[] answers;
boolean canHandInExam;
public Exam(String[] questions) {
exam = questions;
answers = new String[exam.length];
canHandInExam = false;
}
// This method may only be called once in a row
public void handInExam throws NotAllowedException() {
if (canHandInExam) {
// Send exam to teacher
canHandInExam = false;
} else {
throw new NotAllowedException("You may not hand in this exam!");
}
}
public void otherMethod() {
// Do something
canHandInExam = true;
}
}
In this small example it is feasible to slightly adapt each method, however if you would have lots of methods you would need to adapt all of them. Since after all these methods you may again call handInExam() thus the variable canHandInExam would need to be set to true.
Is there a way to solve this problem in a way that is more maintainable? I am open to other possible programming languages that are not OO, but at this point I am unsure of what would be suitable.
I have considered using functional programming (e.g. Haskell) as those languages are not history-sensitive, however I did not know how to limit that you may only call a function once in a row. I tried searching for how to limit a function call to n times in a row both in Java and Haskell, but this ended up with only references to how to call a function n times.
If you speak about handing in an exam, than this doesn't mean that something is done with that exam, but that there is some entity to which the exam is given. So instead of storing within the exam whether it was handed in or can be handed in, something like this would be more appropriate:
//or whatever you call this
public interface Institution {
void handInExam(Exam exam) throws DuplicateExamException;
boolean isHandedIn(Exam exam);
}
Implementations of Institution store the exams that were handed in (possibly using a Set).

Arraylist - compiler is confusing me

For some reason, when I compile this simple code, an error pops up. (If I had 10 rep I would post it) It basically says (File Directory) uses unchecked or unsafe operations. Recompile with -Xlint: unchecked for details. I experimented a little and it seems if I take away the Bin.add() the error goes away. Can someone explain what I should do?
import java.util.ArrayList;
public class Summoned_Bin
{
ArrayList Bin = new ArrayList();
Summoned_Bin()
{
}
void addToBin()
{
Summon summoned = new Summon();
int index = 0;
while (Bin.get(index) != null)
{
index++;
}
Bin.add(index , summoned ); //Without this it runs fine
}
}
I think it wants you to type the list List<Summon> Bin = new ArrayList<Summon>();
Three things to note:
Declare the type as List<Summon> instead of ArrayList<Summon> its best practice to use the interface, which will allow you to change the type at a later date.
The Summoned_Bin class should follow Java naming standards, so SummonedBin should be the name.
Also the name of the SummonedBin object should follow Java naming standards, use bin instead of Bin.
Revised Class
public class SummonedBin {
List<Summon> bin = new ArrayList<Summon>();
SummonedBin() {
}
void addToBin() {
Summon summoned = new Summon();
int index = 0;
while (bin.get(index) != null) {
index++;
}
bin.add(index, summoned);
}
}
It's not error, it's only warning.
You want to do explicit type definition:
ArrayList<Summon> Bin = new ArrayList<Summon>();

Java pattern for parameters of which only one needs to be non-null?

In the last time I often write long functions that have several parameters but use only one of them and the functionality is only different at a few keypoints that are scattered around the function. Thus splitting the function would create too many small functions without a purpose. Is this good style or is there a good general refactoring pattern for this? To be more clear, an example:
public performSearch(DataBase dataBase, List<List<String>> segments) {performSearch(dataBase,null,null,segments);}
public performSearch(DataBaseCache dataBaseCache,List<List<String>> segments) {performSearch(null,dataBaseCache,null,segments);}
public performSearch(DataBase dataBase, List<String> keywords {performSearch(dataBase,null,keywords,null);}
public performSearch(DataBaseCache dataBaseCache,List<String> keywords) {performSearch(null,dataBaseCache,keywords,null);}
/** either dataBase or dataBaseCache may be null, dataBaseCache is used if it is non-null, else dataBase is used (slower). */
private void performSearch(DataBase dataBase, DataBaseCache dataBaseCache, List<String> keywords, List<List<String>> segments)
{
SearchObject search = new SearchObject();
search.setFast(true);
...
search.setNumberOfResults(25);
if(dataBaseCache!=null) {search.setSource(dataBaseCache);}
else {search.setSource(dataBase);}
... do some stuff ...
if(segments==null)
{
// create segments from keywords
....
segments = ...
}
}
This style of code works but I don't like all those null parameters and the possibilities of calling methods like this wrong (both parameters null, what happens if both are non-null) but I don't want to write 4 seperate functions either... I know this may be too general but maybe someone has a general solution to this principle of problems :-)
P.S.: I don't like to split up a long function if there is no reason for it other than it being long (i.e. if the subfunctions are only ever called in that order and only by this one function) especially if they are tightly interwoven and would need a big amount of parameters transported around them.
I think it is very bad procedural style. Try to avoid such coding. Since you already have a bulk of such code it may be very hard to re-factor it because each method contains its own logic that is slightly different from other. BTW the fact that it is hard is an evidence that the style is bad.
I think you should use behavioral patterns like
Chain of responsibilities
Command
Strategy
Template method
that can help you to change your procedural code to object oriented.
Could you use something like this
public static <T> T firstNonNull(T...parameters) {
for (T parameter: parameters) {
if (parameter != null) {
return parameter;
}
}
throw new IllegalArgumentException("At least one argument must be non null");
}
It does not check if more than one parameter is not null and they must be of the same type, but you could use it like this:
search.setSource(firstNonNull(dataBaseCache, database));
Expecting nulls is an anti-pattern because it litters your code with NullPointerExceptions waiting to happen. Use the builder pattern to construct the SearchObject. This is the signature you want, I'll let you figure out the implementation:
class SearchBuilder {
SearchObject search = new SearchObject();
List<String> keywords = new ArrayList<String>();
List<List<String>> segments = new ArrayList<List<String>>();
public SearchBuilder(DataBase dataBase) {}
public SearchBuilder(DataBaseCache dataBaseCache) {}
public void addKeyword(String keyword) {}
public void addSegment(String... segment) {}
public void performSearch();
}
I agree with what Alex said. Without knowing the problem I would recommend following structure based on what was in the example:
public interface SearchEngine {
public SearchEngineResult findByKeywords(List<String> keywords);
}
public class JDBCSearchEngine {
private DataSource dataSource;
public JDBCSearchEngine(DataSource dataSource) {
this.dataSource = dataSource;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// Find from JDBC datasource
// It might be useful to use a DAO instead of datasource, if you have database operations other that searching
}
}
public class CachingSearchEngine {
private SearchEngine searchEngine;
public CachingSearchEngine(SearchEngine searchEngine) {
this.searchEngine = searchEngine;
}
public SearchEngineResult findByKeywords(List<String> keywords) {
// First check from cache
...
// If not found, then fetch from real search engine
SearchEngineResult result = searchEngine.findByKeywords(keywords);
// Then add to cache
// Return the result
return result;
}
}

Categories

Resources