How to use an existing ArrayList inside Lambda Expression/block? - arraylist

I am new to Java 8 and was trying to rewrite an existing code snippet logic using the Java 8 features.
However I am not sure how to use an existing arrayList defined outside the block to get values from it when it is placed inside the lambda block. It complains that it has to be final or effectively final.
I started with converting the inner traditional for loop and encountered the same issues with a counter variable which I was able to sort using AtomicInteger but am not sure how to do that for arrayList as well as I cannot also define the arrayList inside the lambda block since it has a dependency of an i variable that is present in the outer while loop.
Any help will be much appreciated !!! Thanks in advance.
Below is my code snippet :-
public String somemethod(ArrayList someValues){
int i=0;
String status="Failed";
ArrayList someOtherValues = new ArrayList();
try
{
while ( i < (someValues.size()))
{
someOtherValues = (ArrayList) someValues.get(i);
someOtherValues.replaceAll(t -> Objects.isNull(t) ? "" : t); //converting every null to "" within the arrayList someOtherValues
int count=4;
AtomicInteger counter=new AtomicInteger(5);
if(!someOtherValues.get(0).toString().equals(""))
{
while ( count < (someOtherValues.size()))
{
IntStream.range(0, 3).forEach(k -> {
someObjectClass someObject=new someObjectClass();
someOtherObjectClass id = new someOtherObjectClass(someOtherValues.get(0).toString(),someOtherValues.get(count).toString()) //Line where the error is
someObject=new someObjectClass(id);
someObject.setId(id);
if(someCondition)
{
try
{
someObject.setSomething(someValue);
counter.incrementAndGet()
}
}
someObject.setsomeOtherValues1(someOtherValues.get(1).toString());
someObject.setsomeOtherValues2(someOtherValues.get(3).toString())
}
count=counter.get();
counter.incrementAndGet();
}
}
i++;
}
catch(Exception e)
{
return status;
}
}
Right now where it is pending is it complains that someOtherValues, which is an existing arrayList defined outside the lambda block needs to be final or effectively final in order to fetch elements.
Is it literally not possible to change/optimize the above function into a fewer lines of code using Java 8 streams/lambdas/forEach ?

As a general rule it is not a good idea to try and change outside variables inside a lambda definition. But since Java's very loose concept of final fields and variables only applies to assigning values, it can still be done.
The only thing you cannot do in a lambda expression with variable defined outside is assigning new values.
So this does not compile:
List<String> lst = new ArrayList<>();
myLambda = e -> {
lst = new ArrayList<>(); //this violates the 'final' rule
lst.add(e);
}
It is however possible to call any method of the outside variable, even if it changes the state of the variable. This will work:
myLambda = e -> {
lst.add(e);
}
Even though you're still changed the state of the variable lst, this is legal code.
But I strongly advise against it. Lambdas are meant to used in a functional matter and should not change any variables defined elsewhere. It's a better choice to create a list inside the lambda, return it from the lambda and then add it to the outside list.

Related

How to remove element from iterator if condition depends on property of the object the iterator is based on?

Let me elaborate:
I need to be able to iterate over a list of objects. Each of the objects has a property which is a list, and I have to check if that list contains any elements that are not in another list.
When I tried to do it by using nested for loops, it kept giving me concurrent modification exceptions, so I tried to use an iterator, but now I'm stuck, since if I make an iterator based on the list of objects, I can't access the individual object's properties to then iterate over.
Here's some example code of what I was trying to accomplish:
for (preference in preferencesWithRestaurant) {
for (restaurantID in preference.restaurantIDs) {
// One method I tried using
preferencesWithRestaurant.removeIf{ !listOfIds.contains(restaurantID) }
/* alternate method I tried using
if (!listOfIds.contains(restaurantID)) {
preferencesWithRestaurant.remove(preference)
}
*/
}
}
If you can replace the value of preferencesWithRestaurant or store the result in another variable then you can filter it:
preferencesWithRestaurant = preferencesWithRestaurant.filter { preference ->
preference.restaurantIDs.all { it in listOfIds }
}
Depending on the exact type of preferencesWithRestaurant you may need to convert it to the proper type, e.g. invoke toMutableList() at the end.
If you prefer to modify preferencesWithRestaurant in-place, then you can use retainAll() (thanks #Tenfour04):
preferencesWithRestaurant.retainAll { preference ->
preference.restaurantIDs.all { it in listOfIds }
}
Alternatively, you can keep your original approach, but use a mutable iterator to remove an item while iterating:
val iter = preferencesWithRestaurant.listIterator()
for (preference in iter) {
for (restaurantID in preference.restaurantIDs) {
if (!listOfIds.contains(restaurantID)) {
iter.remove()
break
}
}
}

Why .map on a mutableList doesn't actually change values inside of List in Kotlin?

This is what I have and what I want to achieve:
I have a class which has a mutableList as a field.
I want to find a specific element inside that list and change it.
This is what I've tried so far:
This is the functional statement I was hoping would have worked, after I've also put it in an Extension function:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.map { l -> l.name = modifiedName }
.toList()
}
But the list students appears to be unchanged after this function is called.
I found an "ugly" solution with the code below:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
for (l : Student in this.students) {
if (l.id == id) {
l.name = modifiedName
break
}
}
}
Still tho, I'd really like to know why the first block of code behaves like it does and doesn't actually have any effect on the list.
You can think of map as a way to transform input to get new output. Normally it should not mutate state inside, in other words it should be a function without side effects to pursue maintainability
In your case you clearly want to mutate elements, for that you might want to use that code snippet:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.onEach { l -> l.name = modifiedName }
}
Also, even you used map incorrectly it should must modify field l.name (unless you have implemented you own delegates or getter/setter). Try to debug set breakpoint on this.students.filter { l -> l.id == id } and see if there are any items left after filtering
Noob here but I did just see something related to this the other day.
Is there a reason you wouldn't just check to see if your array contains the old value, return the element id and then assign your new value to that id?
I guess I'm just pointing out that this could be accomplished with a "value in array" type search... but I'm still too new to know the pros and cons of using it vs map.
Kind of like this below, which I got from Kotlin - Idiomatic way to check array contains value
"value" in array
Which translates into the Java API:
array.contains("value")
So I'd check for the old value in the array, return it's index and then reassign that index with the new value.

Writing Custom Rule for Android-Lint

Q (tldr;): How do I use the JavaScanner in android-lint to check if a particular function call with a specific string as a parameter has been surrounded by a try/catch block.
Details: I have completed the android-lint tutorials on the official site and have gone through the source of the existing lint-checks. However, I can't seem to grasp the workflow for this AST-based parsing of JavaScanner. What I'm trying to achieve is to catch a function that sets a specific property and surround it with a try/catch block. For example:
MyPropertySettings.set("SOME_PROPERTY", "SOME_VAL");
should not trigger the lint rule but:
MyPropertySettings.set("SOME_SENSITIVE_PROPERTY", "SOME_VAL");
should because it's not surrounded by a try/catch block with SetPropertyException. I don't want to introduce the try/catch to the function itself because it only throws the exception in extremely rare cases (and the internals of the function are based on some reflection mojo).
For this question, even a workflow/hint would be fine. If I can get the first few steps, I might be able to grasp it better.
Update:
After some more study, I have found that I need to set the set function above in getApplicableMethodNames() and then, somehow read the property of that function to decide if the check applies. That part should be easy.
Surrounding try/catch would be more difficult and I gather I would need to do some "flow analysis". How is the question now.
Well, along with the getApplicableMethodNames() method, you need to override the visitMethod() function. You will get the MethodInvocationNode. Just fetch the arguments passed in the invocation using the node.astArguments() function. This returns a list of arguments that you can iterate through using a StrictListAccessor. Check the arguments passed and if it matches your criterion, run a loop and keep calculating the parent node of the invocation node till a try node is found. If it is a try node, then you can get a list of catches using node.astCatches(). Scan the list and find the appropriate exception. If not found, then report.
You can code like this:
check if it is surrounded by try/catch:
#Override
public void visitMethod(JavaContext context, AstVisitor visitor, MethodInvocation node) {
// check the specified class that invoke the method
JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) context.resolve(node);
JavaParser.ResolvedClass clzz = method.getContainingClass();
boolean isSubClass = false;
// sSupportSuperType = {"class name"};
for (int i = 0; i < sSupportSuperType.length; i++) {
if (clzz.isSubclassOf(sSupportSuperType[i], false)) {
isSubClass = true;
break;
}
}
if (!isSubClass) return;
// check if surrounded by try/catch
Node parent = node;
while (true) {
Try tryCatch = context.getParentOfType(parent, Try.class);
if (tryCatch == null) {
break;
} else {
for (Catch aCatch : tryCatch.astCatches()) {
TypeReference catchType = aCatch.astExceptionDeclaration().astTypeReference();
}
parent = tryCatch;
}
}
// get the arguments string
String str = node.astArguments().first().toString();
if (!str.startsWith("\"SOME_PROPERTY\"")) {
context.report(ISSUE, node, context.getLocation(node), "message");
}
}
before this you have to define the specific method by override:
#Override
public List<String> getApplicableMethodNames() {
return Collections.singletonList("set");
}

How do I execute Dynamically (like Eval) in Dart?

Since getting started in Dart I've been watching for a way to execute Dart (Text) Source (that the same program may well be generating dynamically) as Code. Like the infamous "eval()" function.
Recently I have caught a few hints that the communication port between Isolates support some sort of "Spawn" that seems like it could allow this "trick". In Ruby there is also the possibility to load a module dynamically as a language feature, perhaps there is some way to do this in Dart?
Any clues or a simple example will be greatly appreciated.
Thanks in advance!
Ladislav Thon provided this answer on the Dart forum:
I believe it's very safe to say that Dart will never have eval. But it will have other, more structured ways of dynamically generating code (code name mirror builders). There is nothing like that right now, though.
There are two ways of spawning an isolate: spawnFunction, which runs an existing function from the existing code in a new isolate, so nothing you are looking for, and spawnUri, which downloads code from given URI and runs it in new isolate. That is essentially dynamic code loading -- but the dynamically loaded code is isolated from the existing code. It runs in a new isolate, so the only means of communicating with it is via message passing (through ports).
You can run a string as Dart code by first constructing a data URI from it and then passing it into Isolate.spawnUri.
import 'dart:isolate';
void main() async {
final uri = Uri.dataFromString(
'''
void main() {
print("Hellooooooo from the other side!");
}
''',
mimeType: 'application/dart',
);
await Isolate.spawnUri(uri, [], null);
}
Note that you can only do this in JIT mode, which means that the only place you might benefit from it is Dart VM command line apps / package:build scripts. It will not work in Flutter release builds.
To get a result back from it, you can use ports:
import 'dart:isolate';
void main() async {
final name = 'Eval Knievel';
final uri = Uri.dataFromString(
'''
import "dart:isolate";
void main(_, SendPort port) {
port.send("Nice to meet you, $name!");
}
''',
mimeType: 'application/dart',
);
final port = ReceivePort();
await Isolate.spawnUri(uri, [], port.sendPort);
final String response = await port.first;
print(response);
}
I wrote about it on my blog.
Eval(), in Ruby at least, can execute anything from a single statement (like an assignment) to complete involved programs. There is a substantial time penalty for executing many small snippets over most any other form of execution that is possible.
Looking at the problem closer, there are at least three different functions that were at the base of the various schemes where eval might be used. Dart handles at least 2 of these in at least minimal ways.
Dart does not, nor does it look like there is any plan to support "general" script execution.
However, the NoSuchMethod method can be used to effectively implement the dynamic "injection" of variables into your local class environment. It replaces an eval() with a string that would look like this: eval( "String text = 'your first name here';" );
The second function that Dart readily supports now is the invocation of a method, that would look like this: eval( "Map map = SomeClass.some_method()" );
After messing about with this it finally dawned on me that a single simple class can be used to store the information needed to invoke a method, for a class, as a string which seems to have general utility. I can replace a big maintenance prone switch statement that might otherwise be necessary to invoke a series of methods. In Ruby this was almost trivial, however in Dart there are some fairly less than intuitive calls so I wanted to get this "trick" in one place, which fits will with doing ordering and filtering on the strings such as you may need.
Here's the code to "accumulate" as many classes (a whole library?) into a map using reflection such that the class.methodName() can be called with nothing more than a key (as a string).
Note: I used a few "helper methods" to do Map & List functions, you will probably want to replace them with straight Dart. However this code is used and tested only using the functions..
Here's the code:
//The used "Helpers" here..
MAP_add(var map, var key, var value){ if(key != null){map[key] = value;}return(map);}
Object MAP_fetch(var map, var key, [var dflt = null]) {var value = map[key];if (value==null) {value = dflt;}return( value );}
class ClassMethodMapper {
Map _helperMirrorsMap, _methodMap;
void accum_class_map(Object myClass){
InstanceMirror helperMirror = reflect(myClass);
List methodsAr = helperMirror.type.methods.values;
String classNm = myClass.toString().split("'")[1]; ///#FRAGILE
MAP_add(_helperMirrorsMap, classNm, helperMirror);
methodsAr.forEach(( method) {
String key = method.simpleName;
if (key.charCodeAt(0) != 95) { //Ignore private methods
MAP_add(_methodMap, "${classNm}.${key}()", method);
}
});
}
Map invoker( String methodNm ) {
var method = MAP_fetch(_methodMap, methodNm, null);
if (method != null) {
String classNm = methodNm.split('.')[0];
InstanceMirror helperMirror = MAP_fetch(_helperMirrorsMap, classNm);
helperMirror.invoke(method.simpleName, []);
}
}
ClassMethodMapper() {
_methodMap = {};
_helperMirrorsMap = {};
}
}//END_OF_CLASS( ClassMethodMapper );
============
main() {
ClassMethodMapper cMM = new ClassMethodMapper();
cMM.accum_class_map(MyFirstExampleClass);
cMM.accum_class_map(MySecondExampleClass);
//Now you're ready to execute any method (not private as per a special line of code above)
//by simply doing this:
cMM.invoker( MyFirstExampleClass.my_example_method() );
}
Actually there some libraries in pub.dev/packages but has some limitations because are young versions, so that I can recommend you this library expressions to dart and flutter.
A library to parse and evaluate simple expressions.
This library can handle simple expressions, but no blocks of code, control flow statements and so on. It supports a syntax that is common to most programming languages.
There I create an example of code to evaluate arithmetic operations and comparations of data.
import 'package:expressions/expressions.dart';
import 'dart:math';
#override
Widget build(BuildContext context) {
final parsing = FormulaMath();
// Expression example
String condition = "(cos(x)*cos(x)+sin(x)*sin(x)==1) && respuesta_texto == 'si'";
Expression expression = Expression.parse(condition);
var context = {
"x": pi / 5,
"cos": cos,
"sin": sin,
"respuesta_texto" : 'si'
};
// Evaluate expression
final evaluator = const ExpressionEvaluator();
var r = evaluator.eval(expression, context);
print(r);
return Scaffold(
body: Container(
margin: EdgeInsets.only(top: 50.0),
child: Column(
children: [
Text(condition),
Text(r.toString())
],
),
),
);
}
I/flutter (27188): true

Controller selection

In my title screen, i have a code saying that the first controller using A is the PlayerIndex.one.
Here is the code:
public override void HandleInput(InputState input)
{
for (int anyPlayer = 0; anyPlayer <4; anyPlayer++)
{
if (GamePad.GetState((PlayerIndex)anyPlayer).Buttons.A == ButtonState.Pressed)
{
FirstPlayer = (PlayerIndex)anyPlayer;
this.ExitScreen();
AddScreen(new Background());
}
}
}
My question is: How can i use the "FirstPlayer" in other classes? (without this, there is no interest in this code)
I tried the Get Set thing but i can't make it work. Does i need to put my code in another class? Do you use other code to make this?
Thanks.
You can make a static variable say : SelectedPlayer,
and assign first player to it!
then you can call the first player through this class,
for example
class GameManager
{
public static PlayerIndex SelectedPlayer{get;set;}
..
..
..
}
and right after the loop in your code, you can say:
GameManager.SelectedPlayer = FirstPlayer;
I hope this helps, if your code cold be clearer that would be easier to help :)
Ok, so to do this properly you're going to have to redesign a little.
First off, you should be checking for a new gamepad input (i.e. you should be exiting the screen only when 'A' has been newly pressed). To do this you should be storing previous and current gamepad states:
private GamePadState currentGamePadState;
private GamePadState lastGamePadState;
// in your constructor
currentGamePadState = new GamePadState();
lastGamePadState = new GamePadState();
// in your update
lastGamePadState = currentGamePadState;
currentGamePadState = GamePad.GetState(PlayerIndex.One);
Really what you need to do is modify your class that deals with input. The basic functionality from your HandleInput function should be moved into your input class. Input should have a collection of functions that test for new/current input. For example, for the case you posted:
public Bool IsNewButtonPress(Buttons buton)
{
return (currentGamePadState.IsButtonDown(button) && lastGamePadState.IsButtonUp(button));
}
Then you can write:
public override void HandleInput(InputState input)
{
if (input.IsNewButtonPress(Buttons.A)
{
this.ExitScreen();
AddScreen(new Background());
}
}
Note: this will only work for one controller. To extend the implementation, you'll need to do something like this:
private GamePadState[] currentGamePadStates;
private GamePadState[] lastGamePadStates;
// in your constructor
currentGamePadStates = new GamePadState[4];
currentGamePadStates[0] = new GamePadState(PlayerIndex.One);
currentGamePadStates[1] = new GamePadController(PlayerIndex.Two);
// etc.
lastGamePadStates[0] = new GamePadState(PlayerIndex.One);
// etc.
// in your update
foreach (GamePadState s in currentGamePadStates)
{
// update all of this as before...
}
// etc.
Now, you want to test every controller for input, so you'll need to generalise by writing a function that returns a Bool after checking each GamePadState in the arrays for a button press.
Check out the MSDN Game State Management Sample for a well developed implementation. I can't remember if it supports multiple controllers, but the structure is clear and can easily be adapted if not.