Im developing for android and compiling with gradle from git using jitpack.io
Im trying to use this library from git for functional programming:
fj - functional programmming for Java 7
I ran the code and got errors even though everything is tested.
The problem is in the class GroupBy:
Source code:
public Collection<Group<S,T>> execute(Collection<T> collection){
Hashtable<S, Group<S, T>> groups = new Hashtable<S, Group<S, T>>();
for (T item: collection){
S classification = grouper.select(item);
if (!groups.contains(classification)){
groups.put(classification, new Group<S, T>(classification));
}
groups.get(classification).add(item);
}
return groups.values();
}
De-Compiled code:
public Collection<GroupBy.Group<S, T>> execute(Collection<T> collection) {
Hashtable groups = new Hashtable();
Object item;
Object classification;
for(Iterator var3 = collection.iterator(); var3.hasNext(); ((GroupBy.Group)groups.get(classification)).add(item)) {
item = var3.next();
classification = this.grouper.select(item);
if(!groups.contains(classification)) {
groups.put(classification, new GroupBy.Group(classification));
}
}
return groups.values();
}
I would appreciate any help.
Currently i dont see any reason why the code look different
Thanks
The short answer is that when java is complied information is lost. However the decompiled code functions exactly the same as the code you wrote.
Let's look at it line by line...
public Collection<GroupBy.Group<S, T>> execute(Collection<T> collection) {
This is the same, though it's given the Group class its full name.
Hashtable groups = new Hashtable();
Object item;
Object classification;
As you can see here the variable names and all the generic information is lost. Generics in java can be thought of as a hint to the compiler to check for errors. Once the compiler has finished compiling the information is thrown away (generally).
for(
Iterator var3 = collection.iterator();
var3.hasNext();
((GroupBy.Group)groups.get(classification)).add(item)
) {
The enhanced for loop has been replaced by a classic for loop. This is because in bytecode they are the same thing (though a smarter decompiler might have figured this out and written an enhanced for loop here).
The other interesting thing here is that the compiler has put the groups.get(...).add(...) statement inside your for loop. If you think about the contract of for(initialisation; termination; increment) then increment happens upon every loop iteration. So even though you wrote your statement inside the loop, it is the same effect. [There's probably a good reason for doing it this way, I'm not a compiler guru though so I can't say for certain].
item = var3.next();
classification = this.grouper.select(item);
if(!groups.contains(classification)) {
groups.put(classification, new GroupBy.Group(classification));
}
}
return groups.values();
}
The rest of the code is pretty much exactly what you wrote.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Some background: I am new to Java and am taking a basic java class. I am currently on the final project for the class and completed everything except for this last bit of code. For some reason, I am having the toughest time deleting an element from an array list. Here is the code I am working on:
public static void delete(String bookID) {
for (book eachElement : catalog) {
if (eachElement.getBookID().equals(bookID)) {
catalog.remove(eachElement);
return;
}
}
}
code executes, no run time errors but it won't delete anything.
also, I know everything works prior to the remove statement because I have another method that computes calculations using the same exact for and if statement with a select bookID string.
You should not and cannot remove an Element from a Collection while being in a forEach loop.
Please read the Documentation for ArrayList in Java.
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
There you actually can see, that ArrayList.remove(Object o), removes o if it is in the list, so your method is not needed.
So the answer is, find the book Object with your ID and then remove it. Or better use a Map to store your data.
In your case it would be
Book b = null;
for(Book book : books) {
if(book.getBookId().equals(bookId)) {
b = book.getBookId();
break;
}
}
books.remove(b);
Or if you are into Java8 which you really should be :D
books.stream().filter(b -> b.getBookId().equals(bookId)).getFirst().ifPresent(books::remove);
You need to use iterator, otherwise you will get java.util.ConcurrentModificationException
public static void delete(String bookID) {
for (Iterator<Book> it = catalog.listIterator(); it.hasNext(); ) {
Book book = it.next();
if (book.getBookID().equalsIgnoreCase(bookID)) {
it.remove(book);
return;
}
}
}
Note: equalsIgnoreCase is used to discard case differences.
java.util.ConcurrentModificationException is thrown, because you are doing 2 operations on the list: iteration and removal. So, actually, there is another approach - copy the list on each step of iteration.
public static void delete(String bookID) {
for (Book book : new ArrayList<>(catalog)) {
if (book.getBookID().equalsIgnoreCase(bookID)) {
catalog.remove(book);
return;
}
}
}
Note: Because of performance considerations (quadratic memory usage and linear removal on each step), I don't recommend the last approach. I give this example only to stress out the underlying reason why java.util.ConcurrentModificationException is thrown.
Removal of elements, while an iterator is being used, is undefined.The better approach would be to use removeIf.
catalog.removeIf(eachElement -> eachElement.getBookID().equals(bookId));
You need to use iterator in order to delete item while using loop .
also double check if the id exist (make some System.out.println("test") and check if it is entering the scope).
So I have a Method
public modifiers Foo foo(Bar bar){
blah;
blah;
veryInterestingStmt;
moreBlah();
return XYZ;
}
I now want to split this method s.t. everything in its body is extracted into a separate method (programmatically).
I.e.
public modifiers Foo foo(Bar bar){
return trulyFoo(bar);
}
public modifiers Foo trulyFoo(Bar bar){
blah;
blah;
veryInterestingStmt;
moreBlah();
return XYZ;
}
How do I do that, though?
The naive
private void fracture(SootMethod sm) {
SootClass sc = sm.getDeclaringClass();
String auxMethodName = sm.getName() + FRACTURE_SUFFIX;
Type auxReturnType = sm.getReturnType();
List<Type>auxParamTypes = new LinkedList<>(sm.getParameterTypes());
int auxModifiers = sm.getModifiers();
SootMethod auxMethod = sc.addMethod(new SootMethod(auxMethodName,auxParamTypes,auxReturnType,auxModifiers));
Body body = sm.getActiveBody();
Body auxBody = Jimple.v().newBody(auxMethod);
auxMethod.setActiveBody(auxBody);
for(Local l : body.getLocals()){
auxBody.getLocals().add(l);
}
PatchingChain<Unit> units = body.getUnits();
PatchingChain<Unit> auxUnits = auxBody.getUnits();
Iterator<Unit> it = body.getUnits().snapshotIterator();
boolean passedFirstNonidentity = false;
while(it.hasNext()){
Stmt stmt = (Stmt) it.next();
if(!passedFirstNonidentity && !(stmt instanceof IdentityStmt)) {
passedFirstNonidentity = true;
//TODO: if added more parameters than original method had, add their identity stmts here
}
auxUnits.add(stmt);
// if(passedFirstNonidentity) units.remove(stmt); //TODO: uncomment this and later add call to {#code auxMethod}
}
}
}
Doesn't work. If I run, say
DirectedGraph dg = new ExceptionalUnitGraph(auxMethod.getActiveBody());
I get a
java.lang.RuntimeException: Unit graph contains jump to non-existing target
at soot.toolkits.graph.UnitGraph.buildUnexceptionalEdges(UnitGraph.java:128)
at soot.toolkits.graph.ExceptionalUnitGraph.initialize(ExceptionalUnitGraph.java:258)
at soot.toolkits.graph.ExceptionalUnitGraph.<init>(ExceptionalUnitGraph.java:159)
at soot.toolkits.graph.ExceptionalUnitGraph.<init>(ExceptionalUnitGraph.java:192)
The technique of moving code without altering the behavior of the code is called Refactoring and is nicely covered in a book by Martin Fowler.
In your case, I would take the following multi-step approach:
Stand up a "do nothing" function in the function you wish to split, just above the lines of code you wish to move.
Move one or two of those lines of code from the surrounding function int the "do nothing" function, splitting the function, but having the split be a nested call.
Move the split function up (or down) to the edge of the block in the surronding function.
Move teh slpit function out of the block, placing new calls to it either prior to every call of the original function, or after every call of the original function. Note that you may have to rework the handling of return parameters, depending on the details.
It is strongly suggested that you write a set of tests to validate some, if not most, of the overall functionality of this block first. Then, after each change run your tests to verify that you didn't change behavior.
What you are seeing now is a change in behavior which came about by modifying the text of the code in such a manner that it did change behavior. The set of safe transformations of source code is likely smaller than you previously believed, or maybe you just made a simple error. However, the work you are attempting requires more knowledge than can be expressed in a StackOverflow style, question / answer, format. That's why I made the book reference.
If you can narrow the scope, you might get a better response in a future resubmission.
It seems that moving stmts just doesn't work. In contrast, completely replacing the body
Body originalBody = sm.getActiveBody();
originalBody.setMethod(auxMethod);
auxMethod.setActiveBody(originalBody);
Body newBody = Jimple.v().newBody(sm);
sm.setActiveBody(newBody);
and then regenerating the locals, identity stmts (and other stmts you may need) in the newBody looks like a sensible way to go.
I've got a database of playerdata that has some pre-existing fields from previous versions of the program. Example out-dated document:
{
"playername": "foo"
}
but a player document generated under the new version would look like this:
{
"playername": "bar",
"playercurrency": 20
}
the issue is that if I try to query playercurrency on foo I get a NullPointerException because playercurrency doesn't exist for foo. I want to add the playercurrency field to foo without disturbing any other data that could be stored in foo. I've tried some code using $exists Example:
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playername", "")));
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playercurrency", 20)));
My thought is that it updates only playercurrency because it doesn't exist and it would leave playername alone becuase it exists. I might be using exists horribly wrong, and if so please do let me know because this is one of my first MongoDB projects and I would like to learn as much as I possibly can.
Do you have to do this with java? Whenever I add a new field that I want to be required I just use the command line to migrate all existing documents. This will loop through all players that don't have a playercurrency and set it to 0 (change to whatever default you want):
db.players.find({playercurrency:null}).forEach(function(player) {
player.playercurrency = 0; // or whatever default value
db.players.save(player);
});
This will result in you having the following documents:
{
"playername" : "foo",
"playercurrency" : 0
}
{
"playername" : "bar",
"playercurrency" : 20
}
So I know that it is normally frowned upon on answering your own question, but nobody really posted what I ended up doing I would like to take this time to thank #Mark Watson for answering and ultimately guiding me to finding my answer.
Since checking if a certain field is null doesn't work in the MongoDB Java Driver I needed to find a different way to know when something is primed for an update. So after a little bit of research I stumbled upon this question which helped me come up with this code:
private static void updateValue(final String name, final Object defaultValue, final UUID key) {
if (!exists(name, key)) {
FindIterable iterable = players.find(new Document("_id", key));
iterable.forEach(new Block<Document>() {
#Override
public void apply(Document document) {
players.updateOne(new Document("_id", key), new Document("$set", new Document(name, defaultValue)));
}
});
}
}
private static boolean exists(String name, UUID key) {
Document query = new Document(name, new Document("$exists", true)).append("_id", key);
return players.count(query) == 1;
}
Obviously this is a little specialized to what I wanted to do, but with little revisions it can be easliy changed to work with anything you might need. Make sure to replace players with your Collection object.
I'm a newbie with Apache-Spark. I wanna know how to reset the pointer to Iterator in MapReduce function in Apache Spark so that I wrote
Iterator<Tuple2<String,Set<String>>> iter = arg0;
but it isn't working. Following is a class implementing MapReduce function in java.
class CountCandidates implements Serializable,
PairFlatMapFunction<Iterator<Tuple2<String,Set<String>>>, Set<String>, Integer>,
Function2<Integer, Integer, Integer>{
private List<Set<String>> currentCandidatesSet;
public CountCandidates(final List<Set<String>> currentCandidatesSet) {
this.currentCandidatesSet = currentCandidatesSet;
}
#Override
public Iterable<Tuple2<Set<String>, Integer>> call(
Iterator<Tuple2<String, Set<String>>> arg0)
throws Exception {
List<Tuple2<Set<String>,Integer>> resultList =
new LinkedList<Tuple2<Set<String>,Integer>>();
for(Set<String> currCandidates : currentCandidatesSet){
Iterator<Tuple2<String,Set<String>>> iter = arg0;
while(iter.hasNext()){
Set<String> events = iter.next()._2;
if(events.containsAll(currCandidates)){
Tuple2<Set<String>, Integer> t =
new Tuple2<Set<String>, Integer>(currCandidates,1);
resultList.add(t);
}
}
}
return resultList;
}
#Override
public Integer call(Integer arg0, Integer arg1) throws Exception {
return arg0+arg1;
}
}
If iterator can not be reset in the function how can I iterate the parameter arg0 several times? I already tried some different ways as following code but it is also not working. The following code seems like 'resultList' has too many data than I expected.
while(arg0.hasNext()){
Set<String> events = arg0.next()._2;
for(Set<String> currentCandidates : currentCandidatesSet){
if(events.containsAll(currentCandidates)){
Tuple2<Set<String>, Integer> t =
new Tuple2<Set<String>, Integer>(currentCandidates,1);
resultList.add(t);
}
}
}
How can I solve it?
Thanks in advance for your answer and sorry for my poor english. If you don't understand my question please make a comment
An Iterator can't be 'reset' in plain Java or Scala, even. That's the nature of an Iterator. An Iterable is something that can provide you Iterators many times. Your code needs to be rewritten to accept an Iterable, if that's what you really want to do.
The hadoop iterator could theoretically be reset to the beginning if it was cloneable. Reseting to the beginning in a Mapreduce framework would be acceptable since you would still get to read the file from the beginning getting better overall speed. Reseting the iterator to a random point would be counter to the Mapreduce mind set because it would likely require random access from a file.
There is a ticket in Hadoop's Jira explaining why they chose not to make the iterator cloneable although it does indicate that it is possible that it would be since the values would not have to be stored in memory.
I'm sure there must be a standard way to do this, but my attempts to search Stackoverflow have failed.
I have a method like:
public void processSomeWidgetsForUser(int userItemId) {
Iterator<Widgets> iter = allWidgets.values().iterator();
while(iter.hasNext()) {
Widget thisWidget = iter.next();
if (userItemId == -1 || thisWidget.getUsersItemId() == userItemId) {
widget.process();
}
}
}
As you can see -1 is a "special value" meaning process all. Doing this saves repeating the loop code in another method called processSomeWidgetsForAllUsers.
But I dislike special values like this because they are easy to misuse or misunderstand, which is exactly the situation what I'm having to fix now (where someone thought -1 meant something else).
I can only think of two ways to improve this.
have a constant, containing -1 called something like
Widget.ALLWIDGETS which at least is self-documenting, but doesn't
stop code from using a -1 (if someone integrates old code in, for
example)
change the method to take a list of all user ids to
process, which can be empty, but that doesn't seem great
performance-wise (would need to retrieve all user ids first and then loop through
removing. Also what happens if the number of widgets in the list changes between
retreiving the ids and removing
Is there a better way? I'm sure I'm missing something obvious.
The above code has been changed slightly, so may not compile, but you should get the gist.
Although somewhat redundant, a fairly neat self-documenting approach could be to have 3 methods rather than one;
Make your original method private, and make one small change which would be to add your static final int EXECUTE_ALL = -1 and use that in your original method, then add the two new methods;
public void processWidget(int wID) throws IllegalArgumentException {
if(wID == EXECUTE_ALL) throw new IllegalArgumentException();
originalMethod(wID);
}
public void processAllWidgets() {
originalMethod(EXECUTE_ALL);
}
It makes your class a little more cluttered, but as far as the exposed methods go, it is clearer and hopefully foolproof. You could alter it not to throw an exception and just ignore any invalid ids, that just depends on your situation.
This approach of course has the major downside that it changes how the class appears to other classes, breaking everything that currently uses the, now private, originalMethod().
Number 1 would work very nicely. Be sure to document what the variable is though, so future coders (possibly yourself) know what it means.
/**This is the explanation for the below variable*/
public final static int ALL_WIDGETS = -1;
Have an external method like so:
static boolean idRepresentsAll(int id) {
return id == -1;
}
In this case, if you decide to replace it with a different mechanism, you only replace your magic number one place in your code.
At the very least, you would want to do something like this:
public static final int ID_REPRESENTING_ALL = -1;
You can change the method signature to accept a boolean for when you want to process them all.
public void processSomeWidgets(boolean doAll, int userItemId) {
Iterator<Widgets> iter = allWidgets.values().iterator();
while(iter.hasNext()) {
Widget thisWidget = iter.next();
if (doAll || thisWidget.getUsersItemId() == userItemId) {
widget.process();
}
}
}
This makes it more explicit, and easier to read in my opinion as there are no special values.