Java - Recursion - Exception in thread "main" java.lang.StackOverflowError - java

i ran into an issue when trying to print out a list of file dependencies.
About the program:
Scans given *.c files for dependencies, more specifically looks for "#include "%"
Find those files and scans them for their dependencies recursively
All information is stored in a ConcurrentHashMap(key:String value:Linked List of Strings) theTable, where Linked List of Strings contains the list of dependencies.
After processing a certain file, i end up with the following hash table:

If I understand what the map output is saying, there is a cycle ( a #include loop ) in your header files.
i_50.h=[i_35.h, i_28.h, i_45.h, i_44.h, i_46.h],
....
i_35.h=[i_50.h, i_51.h]
That means that your dependencies are a graph and not a DAG. And that in turn means that a simple recursive walk will not work.
By the looks of it, you are attempting to do a graph walk, but for some reason your cycle detection / avoidance is not working, and your algorithm goes into "infinite" recursion.
After looking at the code, I think I can see where the problems are. In the first method, you check that a dependency has already been printed, and then set the entry in the alreadyPrinted map to say it has. But you then proceed to print it irrespective. Then in the second method you are (inexplicably) creating a new alreadyPrinted map each time you recurse to the first method. In other words, the logic of your cycle avoidance is broken.
Rather than fixing your code for you, I'm going to suggest that you go to your favourite "data structures and algorithms" text book and look up "graph traversal" in the index. Alternatively, here's an page I found in some online lecture notes:
http://underpop.online.fr/j/java/algorithims-in-java-1-4/ch05lev1sec8.htm
There's also stuff on graph traversal in Wikipedia, and other places. Google for "java recursive graph traversal", and try and find something that makes sense to you.
The general algorithm is something like this:
traverse(Node node):
traverse_0(node, new Set<Node>())
traverse_0(Node node, Set<Node> visited):
if (visited.contains(node))
return
visited.add(node)
for (Node child: node.children)
traverse_o(child, visited)

The only place where you test if a dependency has already been printed, is the first for loop. You should check in the second for loop too!
for (String d : dependencies) {
if (!alreadyPrinted.containsKey(d)) {
LinkedList<String> key = theTable.get(d);
if (key != null)
output += printDependencies(theTable, key, alreadyPrinted);
}
}

It is fairly easy to see that your algorithm recurses, as soon as some dependency looks like:
item: ...., item, ....
(I hear you say: "that cannot happen, because ...". Yet, the SO shows that either it did happen, or your stack is too small.)
By the way, you maintain the map "already printed", but it is nowhere used? This hints to a flaw in your implementation.

As you are maintaining some state (alreadyPrinted and output) I would recommend moving the state to instance-variabes and to use an object and no class-methods.

The problem was that my Graph traversal had cycles which I was not handling. The working code is provided below.
private static String printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, LinkedList<String> dependencies, ConcurrentHashMap<String, Boolean> alreadyPrinted) {
String output = "";
for (String d : dependencies) {
boolean isPrinted = alreadyPrinted.containsKey(d);
if (!isPrinted) {
output += " " + d;
alreadyPrinted.put(d, true);
}
}
for (String d : dependencies) {
LinkedList<String> key = theTable.get(d);
if (key != null) {
LinkedList<String> unvisited = new LinkedList<String>();
for (String filename : key)
if (!alreadyPrinted.containsKey(filename))
unvisited.add(filename);
if (unvisited != null)
output += printDependencies(theTable, unvisited, alreadyPrinted);
}
}
return output;
}
private static void printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, ConcurrentLinkedQueue<String> toProcess) {
String output = "";
for (String current : toProcess) {
ConcurrentHashMap<String, Boolean> alreadyPrinted = new ConcurrentHashMap<String, Boolean>(); // Keeps track of dependencies already printed
output += current + ":" + printDependencies(theTable, theTable.get(current), alreadyPrinted) + "\n";
}
System.out.println(output);
}

Related

Multiple string replacement in a single string generating all possible combinations

I'm trying to replace multiple words in a string with multiple other words. The string is
I have sample {url} with time to {live}
Here the possible values for {url} are
point1
point2
Possible values for {live} are
10
20
The four possible answers are
I have sample point1 with time to 10
I have sample point1 with time to 20
I have sample point2 with time to 10
I have sample point2 with time to 20
This can also increase to three.
I have {sample} {url} with time to {live}
What would be best data structures and good approach to solve this problem ?
You can do it something like:
public static void main(String[] args) {
String inputStr = "I have {sample} {url} with time to {live}";
Map<String, List<String>> replacers = new HashMap<String, List<String>>(){{
put("{sample}", Arrays.asList("point1", "point2"));
put("{live}", Arrays.asList("10", "20"));
put("{url}", Arrays.asList("url1", "url2", "url3"));
}};
for (String variant : stringGenerator(inputStr, replacers)) {
System.out.println(variant);
}
}
public static List<String> stringGenerator(String template, Map<String, List<String>> replacers) {
List<String> out = Arrays.asList(template);
for (Map.Entry<String, List<String>> replacerEntry : replacers.entrySet()) {
List<String> tempOut = new ArrayList<>(out.size()*replacerEntry.getValue().size());
for (String replacerValue : replacerEntry.getValue()) {
for (String variant : out) {
tempOut.add(variant.replace(replacerEntry.getKey(), replacerValue));
}
}
out = tempOut;
}
return out;
}
also you can try make similar solution with recursion
You can use a template string and print the combinations using System.out.format method like below:
public class Combinations {
public static void main(String[] args) {
String template = "I have sample %s with time to %d%n"; //<-- 2 arguments case
String[] points = {"point1", "point2"};
int[] lives = {10, 20};
for (String point : points) {
for (int live : lives) {
System.out.format(template, point, live);
}
}
}
}
The code solves the 2 argument case but it can be easily extended to the 3 cases substituting the sample word with another %s in the template and a triple loop.
I'm using the simplest array structures, it is up to you decide which structure is the more adapt for your code.
Unless you want the hardcoded solution with simple nested loops shown in Dariosicily's answer, you will need to store "replacee-replacements" pairings, for example the string {url} paired with a list of strings point1 and point2. A simple class can do that, like
class StringListPair{
public final String s;
public final List<String> l;
public StringListPair(String s,List<String> l){
this.s=s;
this.l=l;
}
}
and then a list of replacements can be initialized as
List<StringListPair> mappings=Arrays.asList(
new StringListPair("{url}",Arrays.asList("point1","point2")),
new StringListPair("{live}",Arrays.asList("10","20","30")));
(If someone wants to totally avoid having a helper class, these are all strings, so a List<List<String>> can do the job too, having "{url}","point1","point2" lists inside, just then we would have to fight with indexing the inner lists everywhere)
Then two common approaches pop into my mind: a recursive one, generating all possible combinations in a single run, and a direct-indexing one, numbering all combinations and generating any of them directly upon request. Recursion is simpler to come up with, and it has no significant drawbacks if all the combinations are needed anyway. The direct approach generates a single combination at a time, so if many combinations are not going to be used, it can spare a lot of memory and runtime (for example if someone would need a single randomly selected combination only, out of millions perhaps).
Recursion will be, well, recursive, having a completed combination generated in its deepest level, thus it needs the following:
the list of combinations (because it will be extended deep inside the call-chain)
the mappings
the candidate it is working on at the moment
something to track what label it is supposed to replace a the moment.
Then two things remain: recursion has to stop (when no further labels remain for replacement in the current candidate, it is added to the list), or it has to replace the current label with something, and proceed to the next level.
In code it can look like this:
static void recursive(List<String> result,List<StringListPair> mappings,String sofar,int partindex) {
if(partindex>=mappings.size()) {
result.add(sofar);
return;
}
StringListPair p=mappings.get(partindex);
for(String item:p.l)
recursive(result,mappings,sofar.replace(p.s,item),partindex+1);
}
level is tracked by a simple number, partindex, current candidate is called sofar (from "so far"). When the index is not referring to an existing element in mappings, the candidate is complete. Otherwise it loops through the "current" mapping, and calling itself with every replacement, well, recursively.
Wrapper function to creata and return an actual list:
static List<String> userecursive(List<StringListPair> mappings,String base){
List<String> result=new ArrayList<>();
recursive(result, mappings, base, 0);
return result;
}
The direct-indexing variant uses some maths. We have 2*3 combinations in the example, numbered from 0...5. If we say that these numbers are built from i=0..1 and j=0..2, the expression for that could be index=i+j*2. This can be reversed using modulo and division operations, like for the last index index=5: i=5%2=1, j=5//2=2. Where % is the modulo operator, and // is integer division. The method works higher "dimensions" too, just then it would apply modulo at every step, and update index itself with the division as the actual code does:
static String direct(List<StringListPair> mappings,String base,int index) {
for(StringListPair p:mappings) {
base=base.replace(p.s,p.l.get(index % p.l.size())); // modulo "trick" for current label
index /= p.l.size(); // integer division throws away processed label
}
return base;
}
Wrapper function (it has a loop to calculate "2*3" at the beginning, and collects combinations in a list):
static List<String> usedirect(List<StringListPair> mappings,String base){
int total=1;
for(StringListPair p:mappings)
total*=p.l.size();
List<String> result=new ArrayList<>();
for(int i=0;i<total;i++)
result.add(direct(mappings,base,i));
return result;
}
Complete code and demo is on Ideone

How do I resolve a NullPointerException on a JUNG graph?

So, basically this is what I have so far.
public List<String> cycleSearch(Graph<String,String> g) throws Exception{
List<String> list = null;
Graph<String,String> auxG = g;
for(String aux : g.getVertices()){
String aux2 = aux;
if(g.degree(aux)>1){
if(auxG.removeVertex(aux2)){
for(String d : g.getSuccessors(aux2)){
for(String a : g.getSuccessors(aux)){
if(a!=d){
list = findPath(auxG,d,a);
if(list!=null){
list.add(0,aux);
list.add(aux);
return list;
}
}
}
}
}
}
auxG = g;
}
return null;
}
What the method does is basically to search for a cycle in a hypergraph based on JUNG.
The idea it's to recieve a graph on the parameters and then create a variable (as the same type) to later remove a vertex from it without making any changes on the original graph, just in case a cycle isn't found. That way I can use a method called findPath(,,), once the vertex is removed. The method will 'create' another path without walking through the removed vertex.
My compiler says there is problem right here:
for(String d : g.getSuccessors(aux2))
I've been programming graphs in Java(JUNG) for only 1 month.
HELP
There is a bug in JUNG that this code has turned--getSuccessors() should be returning an empty collection if the graph does not have the vertex, rather than returning null, which is what SetHypergraph's implementation does. Sorry about that. (In general, you can avoid this by wrapping the getSuccessors(x) inside a containsVertex(x) if statement.)
However, the reason why you're encountering this bug is that you're doing at least a couple of things that do not make sense:
(1) you're assigning auxG to g (so they're referencing the same object); this is misleading and not helpful.
Similarly, you're assigning aux2 to aux, which is also misleading.
(2) you're removing aux[2] from auxG and then asking for aux2's successors in auxG. aux2 will not have any successors in auxG once it's removed.
(3) Since aux2 and aux are the same vertex, your innermost loop will also not do anything useful for the same reason; there will be no successors.
You need to rethink your entire algorithm, because this simply is not correct as designed.
Instead of using null to represnt no successors, you could just use an empty list, and thus avoid the NullPointerException. Replace return null; with return new LinkedList<>();.

Iterate over all nodes in a recursively defined tree

I am trying to make a node class that I will eventually be able to use for a minimax search, however I am having trouble iterating over all of the nodes in my tree (in this case for a simple to string function).
Here is the definition of the recursive to string method.
public String toString(){
if(!this.isLeaf()){
String text = "";
Iterator<Node<T>> iter = children.iterator();
while(iter.hasNext()){
Node child = iter.next();
text = "/" + child.toString();
}
return text;
}else{
return cargo.toString() ;
}
}
After reading other answers I tried using the Iterator interface as seen in the code above but it still didn't work. (I'm also open to non-recursive methods of doing this)
Did you mean +=?
text += "/" + child.toString();
^
I assume that you intended to concatenate the child values separated by a '/' as per tom's answer.
If you intend to build up a string, it is more efficient to use a StringBuffer, because otherwise each time around the loop a new String has to be allocated to take the new value, whereas a StringBuffer builds up in a buffer.
StringBuffer text = new StringBuffer();
for (Node<T> child : children) {
text.append('/');
text.append(child.toString());
}
return text.toString;
I've used a for-each style loop but the 'while' loop you used would still work as well.

Understanding code specific functional concepts

I am relatively new to struts and java. I have been trying to understand the following piece of code.
List<LabelValueBean> dbList = getCardProductList();
ConcurrentMap<Integer, ProductItem> ret = new ConcurrentHashMap<Integer, ProductItem>();
for (LabelValueBean lb : dbList) {
ProductItem pi = new ProductItem();
pi.setId(Integer.valueOf(lb.getId()));
pi.setCode(lb.getCode());
pi.setName(lb.getDescription());
LabelValueBeanAuxCol[] aux = lb.getLabelvaluebeanauxcol();
pi.setTypeProduct(Boolean.TRUE);
if (null != aux) {
for (LabelValueBeanAuxCol element : aux) {
if (null != element
&& "PRDCT_SVC_IND".equals(element.getName())) {
pi.setTypeProduct(Boolean.valueOf("Y".equals(element
.getValue())));
}
}
}
pi.setNeedSetup(Boolean.TRUE);
ret.put(pi.getId(), pi);
}
return Himms2LookupUtil
.<ConcurrentMap<Integer, ProductItem>> setValueInCache(
Himms2Names.CARD_SERVICE_PRODUCT_LIST, ret);
}
With repect to the code block around "PRDCT_SVC_IND", how would a name of the column be mapped to the labelvaluebean?
Though I have an idea on the concurrent map and the key value pair functionality, I am pretty unsure about most of the concepts here and have tried searching on the internet without much luck. I would want a more clearer overview of what the above lines actually mean(in general ofcourse), in terms of the concepts used here like the concurrenthashmap, list(labelvaluebean) etc.
Any inputs would be greatly appreciated.
Code is doing following things :-
1) Getting CardProductList in first line and storing reference in a dbList object as
List<LabelValueBean> dbList = getCardProductList();`
2) Creating ConcurrentMap of key value .
3) Start iterating CardProductList and perform following operations on each CardProductList object -
a) Crates ProductItem object.
b) setting CardProduct object values (id, code, name) into ProductItem object.
d) setting ProductItem.typeProduct to TRUE.
c) getting Labelvaluebeanauxcol and store it in a LabelValueBeanAuxCol[] array instance called aux.
d) now check if aux is not null then iterates aux array and checks if(elemet is not null AND element name IS EQUAL TO "PRDCT_SVC_IND"
THEN
set ProductItem.TypeProduct to True if element.value = Y
ELSE
set ProductItem.TypeProduct to FALE
e) set ProductItem.NeddSetup = TRUE
f) set ProductItem.id and ProductItem into ConcurrentMap.
4) Store ConcurrentMap in cache

Java Collections API HashSet remove method

I encountered this issue while working with the Java Collections API. Basically this is a support method for an implementation of Kruskal's algorithm for finding an MST. I created this class for implementing the union/find algorithm.
My question, as I was able to find a work around, is that does anybody know of any reason why the remove method in the "union" method would not work consistently. That is at run time it would remove some elements and not others. For example I implemented this for a task involving cities and it seemed to not like removing some cities. In particular it repeatedly stumbled on a couple of different sets, but always the same ones. I wondered whether it was a object reference issue, i.e. whether I was testing the wrong thing, but I could not get around it.
I know the rest of my work was correct as I was able to replace it with a loop that eliminated the element, and the algorithm executed perfectly. Probably with slightly worse performance, however.
I was wondering whether anybody can see a mistake. Also I should note that I called it from different class, however, the calls were made with elements that were retrieved using the find method. Note that the find method must work well, since simply altering the remove method made the whole thing work, i.e. it was finding and returning the appropriate objects.
Thanks
Oscar
/*
* A constructor for creating a new object of this class.
*/
DisjointSets()
{
underlying = new HashSet<HashSet<String>>();
}
/*
* A method for adding a set to this DisjointSets object
*/
void add(HashSet<String> h)
{
underlying.add(h);
}
/*
* A method for finding an element in this DisjointSet object.
*/
HashSet<String> find(String s)
{
// Check each set in the DisjointSets object
for(HashSet<String> h: underlying)
{
if(h.contains(s))
{
return h;
}
}
return null;
}
/*
* A method for combining to subsets of the DisjointSets
*/
void union(HashSet<String> h1, HashSet<String> h2)
{
System.out.print("CHECK ON DS\n");
System.out.print("*********************\n");
System.out.print("H1 is : { ");
for (HashSet<String> n: underlying)
{
System.out.print("Set is : { ");
for (String h : n)
{
System.out.print(h + " , ");
}
System.out.print("} \n ");
}
// Add the objects of h1 to h2
// DOES NOT WORK CONSISTENTLY
h1.addAll(h2);
underlying.remove(h2);
}
}
And I replaced it with
HashSet<HashSet<String>> temp = new HashSet<HashSet<String>>();
for(HashSet<String> f: underlying)
{
if(f != h2)
{
temp.add(f);
}
}
underlying = temp;
The problem is that when you modify the contents of one of the nested HashSets, you screw up the internals of the outer HashSet (because the hashCode() of the nested HashSet has changed). in order to maintain this collection correctly, whenever you want to modify one of the nested HashSets you must first remove it from the outer HashSet and then re-add it (if necessary).
(you don't really provide enough code to figure out if that's truly the problem, but that's my best guess).
Set<Set<String>> outerSet = new HashSet<String>();
Set<String> innerSet = new HashSet<String>();
innerSet.add("foo");
outerSet.add(innerSet);
// *** BROKEN ***
innerSet.add("bar"); // <- adding element to innerSet changes result of innerSet.hashCode()
outerSet.remove(innerSet); // <- this may or may not work because outerSet is _broken_
// *** BROKEN ***
// *** CORRECT ***
outerSet.remove(innerSet);
innerSet.add("bar");
// now you can put innerSet back in outerSet if necessary
Following up on #jtahlborn's answer, the contract for AbstractSet.hashCode() says
Returns the hash code value for this
set. The hash code of a set is defined
to be the sum of the hash codes of the
elements in the set. This ensures that
s1.equals(s2) implies that
s1.hashCode()==s2.hashCode() for any
two sets s1 and s2, as required by the
general contract of Object.hashCode.
This implementation enumerates over
the set, calling the hashCode method
on each element in the collection, and
adding up the results.
Code to demonstrate #jtahlborn's answer (which is correct)
import java.util.HashSet;
import java.util.Set;
public class TestHashSetHashCode {
public static void main(String[] args)
{
Set<String> strings = new HashSet<String>();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
strings.add("five");
Set<String> test = new HashSet<String>();
System.out.println("Code "+test.hashCode());
for (String s : strings) {
test.add(s);
System.out.println("Code "+test.hashCode());
}
}
}
Outputs
Code 0
Code 115276
Code 3258622
Code 3368804
Code 113708290
Code 116857384
One more reason to add to the list to make use of immutable collections wherever possible.

Categories

Resources