GdxRuntimeException: #iterator() cannot be used nested - java

I'm working on this game which has a World. In this World there are many Units.
The problem stems from the fact that World serves (among other things) two main tasks:
Iterate through each Unit so that they can update their properties based on time passed an so forth.
Find potential targets for each Unit.
In World, this happens:
for (Actor a : stage.getActors())
{
a.draw(batch, 1);
a.act(10);
findTargets((Unit)a);
}
findTargets() is defined as such:
public ArrayList<Unit> findTargets(Unit source) {
double sight = source.SIGHT;
ArrayList<Unit> targets = new ArrayList<Unit>();
for (Actor a : stage.getActors()) {
Unit target = (Unit)a;
if (!(target instanceof Unit))
continue;
if (target.equals(source)) continue;
if (((Unit)target).getPos().dst(source.getPos()) < sight) {
targets.add((Unit)target);
}
}
return targets;
}
The problem is obvious: findTargets() also iterates over every unit, resulting in a nested iteration. However, I'm unsure as to how I should proceed to "un-nest" this, as I'm only seeing a catch 22: Every unit does in effect have to iterate over every other unit to see if they're within their sight-range.
Some fresh eyes on this would be greatly appreciated.

There may be ways to refactor your design to avoid the nesting. But the simplest solution might be to just use the old school for loops for both outer and inner, or just the inner. Don't use the iterator, as that is not allowed here for nested loops. getActors returns a libGDX Array, so just traverse that by index
for (int i=0; i < stage.getActors().size; i++) {
//...etc --> use stage.getActors().items[i] ...

Related

for list iterator and has to manipulate by index

have a list of bean and I want to manipulate by its index and I tried below way, is there any other way of doing this which is easier and generic?
List<UserBean> resultBean = query.setFirstResult(offset).setMaxResults(limit).getResultList();
for (int i = 0; i < resultBean.size(); i++) {
resultBean.get(i).setChabi(encode(decyptChabi(resultBean.get(i).getChabi())));
}
As you can see from the Java Language Specification (JLS), 14.14, there are two kinds of for loops. The basic for loop, which uses an index, and the enhanced for loop, which doesn't.
You used the basic for loop but violated the DRY (Don't Repeat Yourself) principle in that you're calling resultBean.get(i) twice. To cure that, you can introduce a variable which makes the code much more readable:
for (int i = 0; i < resultBean.size(); i++) {
UserBean user = resultBean.get(i);
user.setChabi(encode(decryptChabi(user.getChabi())));
}
In your example, you don't even need the index variable, so you can replace the basic for loop with an enhanced for loop which would be even more concise:
for (UserBean user : resultBean) {
user.setChabi(encode(decryptChabi(user.getChabi())));
}
Whatever you do, prefer code that is easy to read over code that is fast/easy to write.

Java: Merging two lists from complex objects with duplicates to one ordered list

First off my problem is similiar to this already answered question Merging two arrayLists into a new arrayList, with no duplicates and in order, in Java.
However the difference here is that I tried to merge two lists with more than just a String together. The intention on my side was to merge two objects of the following kind (to simplify things I striped unnecessary infos from the example):
public class Data{
private int count;
private Type type;
private Key uniqueKey;
}
So that I get a new oject which has a summarized count out. This will eliminate unwanted duplicates because the uniqueKey on these objects was identical. The reason for this is that I mapped several business types to only one technical type.
The problem here is that you have to account for every possiblity in order to handle the merge correctly and don't miss an original object.
Here are some cases I tried to cover with unit test:
One normal, followed by two duplicates, and one normal = normal, merged, normal
Two duplicates, followed by two normal = merged, normal, normal
Two normal, followed by two duplicates = normal, normal, merged
and so on and so forth...
So how to solve that without going crazy?
Since I spent half a day with that problem, I thought the simple answer might be useful to someone else.
So what did I try:
I decided not to go recursive since I avoid it if I can for obvious reasons and used two nested loops
I wrote unit tests for every case I could think of
Then I tried step by step to make them all green
I banged my head against the table because everytime I made one green another one went red
I asked a colleague
He let me state the problem without showing him my "solution"
Here's the magic 15 min solution:
public static LinkedList<Data> merge(final LinkedList<Data> source) {
final HashMap<Data, Integer> temp = new HashMap<>();
for (final Data data : source) {
final int count = data.getCount();
data.setCount(0);
if (temp.get(data) == null) {
temp.put(data, count);
}
else {
temp.put(data, temp.get(data) + count);
}
}
final Set<Entry<Data, Integer>> set = temp.entrySet();
final LinkedList<Data> result = new LinkedList<>();
for (final Entry<Data, Integer> entry : set) {
final Data mergedData = entry.getKey();
mergedData.setCount(entry.getValue());
result.add(mergedData);
}
Collections.sort(result, new DataComparator());
return result;
}

Using a stack to solve a maze Object Oriented (backtracking) issue

I am trying to solve a maze in an object oriented way.
My maze consists of fields, each field has an element attribute,
an element is a wall, player, helper or endpoint. A field with an empty attribute is a path.
Each field keeps track of his own neighbors in a HashMap.
When the player hits a helper, the helper should solve the maze and show the correct path.
I'm trying to find the endpoint by getting the current location of the helper and storing it's neighbors fields in a stack.
This is the code as far as helper goes.
The loop never ends, and I don't know why?
public void findRoute() {
Collection<Field> c = currentField.getHashMap().values();
Stack<Field> fieldNeighbours = new Stack<Field>();
for (Field field : c) {
fieldNeighbours.push(field);
}
while (!endpointReached) {
Field p = fieldNeighbours.pop();
if (p.getElement().getNaam().equals("endPoint")) {
System.out.println("endPoint Reached! ");
endpointReached = true;
return;
}
if (!p.getElement().getNaam().equals("Wall")) {
if (!p.getHashMap().get("north").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("north"));
}
if (!p.getHashMap().get("south").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("south"));
}
if (!p.getHashMap().get("east").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("east"));
}
if (!p.getHashMap().get("west").getElement().getNaam().equals("wall")) {
fieldNeighbours.push(p.getHashMap().get("west"));
}
}
}
In addition to the stack you need a set of already-visited cells to avoid searching cycles repeatedly.
I'll also point out that using hashes rather than simple references is bad design for most purposes.

How can I use functional programming to do string manipulation?

I'm writing a function where I'm essentially doing the same thing over and over. I have the function listed below
public String buildGarmentsString(List<Garment> garments)
{
StringBuilder garmentString = new StringBuilder(10000);
for(int i=0;i<4;i++)
{
garmentString.append(this.garmentProductId(i,garments.get(i).getProductId()));
garmentString.append(this.garmentColor(i,garments.get(i).getColor()));
for(int j=0;j<garments.get(i).getSizes().size();j++)
{
//check xxsml
if(garments.get(i).getSizes().get(j).getXxsml() >0)
{
garmentString.append(this.garmentSizes(i, Size.xxsml(),garments.get(i).getSizes().get(j).getXxsml()));
}
//check xsml
if(garments.get(i).getSizes().get(j).getXsml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xsml(),garments.get(i).getSizes().get(j).getXsml()));
}
//check sml
if(garments.get(i).getSizes().get(j).getSml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.sml(),garments.get(i).getSizes().get(j).getSml()));
}
//check med
if(garments.get(i).getSizes().get(j).getMed() > 0)
{
garmentString.append(this.garmentSizes(i,Size.med(),garments.get(i).getSizes().get(j).getMed()));
}
//check lrg
if(garments.get(i).getSizes().get(j).getLrg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.lrg(),garments.get(i).getSizes().get(j).getLrg()));
}
//check xlrg
if(garments.get(i).getSizes().get(j).getXlg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xlg(),garments.get(i).getSizes().get(j).getXlg()));
}
//check xxlrg
if(garments.get(i).getSizes().get(j).getXxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxlg(),garments.get(i).getSizes().get(j).getXxl()));
}
//check xxxlrg
if(garments.get(i).getSizes().get(j).getXxxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxxlg(),garments.get(i).getSizes().get(j).getXxxl()));
}
}
}
}
This is my garmentSizes function:
public String garmentSizes(int garmentNumber, String size,int numberToSend)
{
String garmentSizes = "&garment["+garmentNumber+"][sizes]["+size+"]="+numberToSend;
return garmentSizes;
}
I'm trying to figure out how I can get this done with a lot less code. I've read that with functional programming you can do things like pass in functions to parameters to other functions. After doing some reading online, I think I want to do something like this but I'm not sure how or what the best approach would be.
I have done some reading here on stack overflow and I've seen people mention using either the Command pattern or FunctionalJava or LambdaJ for trying to approximate this feature in Java. I've read over the documentation for the two libraries and read the Wikipedia Article on the Command Pattern, but I'm still not sure how I would use any of those to solve my particular problem. Can somebody explain this to me? As somebody that has never done any functional programming this is a bit confusing.
You could use local variables to decrease the amount of repetition. Say bySize = garments.get(i).getSizes().get(j) for example.
instead of size.getXxsml(), size.getXsml() etc. you could use an enum for sizes and loop on sizes.
The whole thing would then look like:
for(int j=0;j<garments.get(i).getSizes().size();j++) {
bySize = garments.get(i).getSizes().get(j);
for (Size s : Size.values()) {
if (bySize.get(s) > 0) {
garmentString.append(garmentSizes(i, s, bySize.get(s)));
}
}
}
The bySize.get(s) method could be implemented either with a switch that directs to the right method or directly in the enum and you could get rid of the getXsml etc. methods.
The only thing which differs between all your checks is this:
getXxsml/xxsml, getXsml/xsml, getSml/sml, etc.
If you could pass these values (as strings) to some upper-level method, and if
that upper-level method could eval i.e. execute these strings, then you can just
have an array of these values and pass that array to that upper-level method.
In Java, you can do something similar with reflection.
All these checks could indeed be simplified to much less
code through the use of reflection.
Look at:
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor
and you will see what I mean.
From your code it appears that some Class has the following methods:
xxsml(), xsml(), sml(), med(), ..., xxxlg()
to get the amounts (?) available for each size.
You can design your data better, like this:
Have a "Size" type, that enumerates all sizes (could be Enum or some class with attribute String key)
Have a method that returns a List of all known sizes.
replace the above methods with amountFor(Size) This could be backed by a Map<Size, Integer>
For backward compatibility, you could rewrite the old methods along the lines:
int xxsml() {
return amountFor(Size.XXSML); // assuming you have a singleton instance
// for each well known size
}
Of course, in getGarmentString, you would then loop through the List of all known sizes:
for (Size sz : Size.getAllKnownSizes()) {
if (garments.get(i).getSizes().get(j).amountFor(sz) > 0) {
... do whatever must be done here
}
}

PMD: Avoid instantiating new objects inside loops

I've got an issue with the PMD rule Avoid instantiating new objects inside loops. Here is some example code:
import java.awt.Dimension;
public class PMDDemo {
public static void main(final String[] args) {
final Dimension[] arr = new Dimension[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = new Dimension(i, i); // rule violation here
}
}
}
PMD gives me the above mentioned rule violation at the marked spot in the code. How am I supposed to create n instances of a class without creating them within a loop?
I know that some of PMD's rules are controversial (like the onlyOneExit rule). But up to now I at least understood the idea behind them. I don't understand the reasoning behind this rule. Can someone help me with that?
For your specific use case it makes no sense as you keep the reference to the new Object after the loop. So there is no real alternative to your solution.
More generally speaking, creating short lived objects in Java is cheap* (apart from the hidden cost that the GC will run more often). In particular, the allocation is almost free and the time of GC mostly depends on the quantity of reachable objects - dead objects do not increase GC time for typical GC algorithms.
The JIT can also perform various optimisations if it detects that unnecessary objects are created.
Obviously, creating useless is not a recommended practice, but trying to reuse objects is often counterproductive.
As a practical example, you can have a look at this post which shows that creating a new set within a loop is cheaper than creating one before the loop and clearing it at each iteration.
* Thanks #RichardTingle for the link
for (int i = 0; i < arr.length; i++) {
arr[i] = new Dimension(i, i); // rule violation here
}
The Above Pmd can be resolved by
for (int i = 0; i < arr.length; i++) {
arr[i] = createNewDimension(i,i); // rule violation here
}
private static Dimension createNewDimension(i,i) {
return new Dimension(i, i);
}
we should not directly use new operator inside a loop just move this inside a private method.

Categories

Resources