Java PowerSet -prints only one - java

Having a problem, only printing one instead of each powerset and I can't quite spot it.
Trying to write a program that gives out a powerset of a given set.
import java.util.HashSet;
import java.util.Iterator;
public class PowerSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
HashSet<HashSet<String>> powerset;
set.add("a");
set.add("b");
set.add("c");
set.add("d");
powerset = powerset(set);
System.out.println(powerset);
}
public static HashSet<HashSet<String>> powerset( HashSet<String> set){
if (set.size()== 0) {
HashSet<HashSet<String>> pset = new HashSet<HashSet<String>>();
HashSet<String> emptySet = new HashSet<String>();
pset.add(emptySet);
return pset;
} else {
HashSet<String> tmp;
Iterator<String> it = set.iterator();
String elt = it.next();
set.remove(elt);
HashSet<HashSet<String>> oldpset = powerset(set);
HashSet<HashSet<String>> newpset = new HashSet<HashSet<String>>();
Iterator<HashSet<String>> psetit = oldpset.iterator();
while(psetit.hasNext()){
tmp = psetit.next();
newpset.add(tmp);
tmp.add(elt);
newpset.add(tmp);
}
return newpset;
}
}
}

One issue I see is that you remove the element elt from set before calling powerset(set). Because Java objects act as pointers, when you remove an element from set at for the current call to powerset, you are modifying all references to it (even references stored on the stack from previous calls).
Another issue I see is that you use set.remove(elt), you should be using it.remove() or you will mess up the iterator.

Related

Reduce repeated elements in a list

To compact in a new list without repeated elements, there may be null elements. I need help .
I have this error "Tester Error (Individual Delivery 4): the method returns []instead of [1] when invoked with [1]".
public <E> PositionList<E> compactar (Iterable<E> lista)
{
if(lista == null){
throw new IllegalArgumentException();
}// if
PositionList<E> newLista = new NodePositionList<E>();
Iterator<E>iterator = lista.iterator();
while(iterator.hasNext())
{
if(eqNull(iterator,iterator.next())) {
newLista.addLast(iterator.next());
}//if
}//while
return newLista;
}//compactar
//-------------assistant--------------------------------------------------------------
public static boolean eqNull (Object o1, Object o2)
{
return o1 == o2 || o1!= null && o1.equals(o2);
}// de eqNUll
}// Operacioncompactar
Not clear if you want to remove all dupes or just remove nulls. These remove dupes.
List<Comparable> l = ...; // The source list
List<Comparable> nl = new ArrayList<>(); // New list without dupes
Collections.sort(l);
Comparable last = UUIDs.randomUUID().toString(); // This one will never be in our source list
for (Comparable c: l) {
if (!Objects.equal(c, last)) { // Or some other null-safe equals function
nl.add(c);
}
last = c;
}
Running time O(nlogn). Elements in list of course need to implement a sensible equals() and hashCode().
Set<?> set = new HashSet<String>(); // Track "seen"
List<?> l = ...; // Original list
List<?> nl = new ArrayList<>(); // New list without dupes
for (Object o: l) {
if (!set.contains(o)) {
nl.add(o);
}
set.add(o);
}
Running time is O(n), since hashset is constant lookup time. Or simpler:
Set<?> set = new HashSet<String>(); // Will be collection without dupes
List<?> l = ...; // Original list
for (Object o: l) {
set.add(o); // Rely on set semantics to remove dupes
}
List<?> nl = new ArrayList<>(set);
Of course the objects in the list must implement a sensible equals() and hashCode().
With java 8, you can use Stream distinct to solve that.
The sample code as below. Hope it will help you.
// input data
List<String> a = new ArrayList<>();
a.add("A");
a.add("A");
a.add("A");
a.add(null);
a.add(null);
Iterator source = a.iterator();
Iterable<String> iterable = () -> source;
// logic code
Iterator temp = StreamSupport
.stream(iterable.spliterator(), false)
.distinct()
.collect(Collectors.toList()).iterator();
Iterable result = () -> temp;
// verify result
StreamSupport
.stream(result.spliterator(), false)
.forEach(System.out::println)
;

Deleting elements from list using another list

I am trying to delete the elements from list1 that are in list1
package listCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Arry2List {
public static void main(String[] args) {
String[] s = {"INDIA" ,"JAPAN","THAILAND","MALAYSIA"};
ArrayList<String> list1= new ArrayList<String>();
String[] s1 = {"THAILAND","MALAYSIA"};
ArrayList<String> list2= new ArrayList<String>();
for(String temp : s)
{
list1.add(temp);
}
for(String temp : s1)
{
list2.add(temp);
}
//removing elements from list1 that are in list2
System.out.println("In list1 **************");
for (String t : list1)
{
System.out.println(t);
}
System.out.println("In list2 **************");
for (String t1 : list2)
{
System.out.println(t1);
}
//editlist(list1,list2);
Iterator<String> i=list1.iterator();
while( i.hasNext() )
{
if ( list2.contains( i.hasNext() ) )
{
i.remove();
}
}
System.out.println("In list1 again **************");
for(int i1 =0;i1<list1.size();i1++)
{
System.out.println(list1.get(i1));
}
}
}
Output should be INDIA,JAPAN.
List1 should contain only those elements which are not in the list2.
I am a beginner to Core Java and trying to learn collections.
In the loop that checks the element using List.contains(), you're passing a boolean (i.hasNext() returns whether the iterator has more elements) instead of the element. This causes the loop to run infinitely because you never call Iterator.next() to get the next element. You should use:
if (list2.contains(i.next())) {
instead of
if (list2.contains(i.hasNext())) {
It's better practice to also save the next element in a variable for re-usability:
while (i.hasNext()) {
String element = i.next();
if (list2.contains(element)) {
i.remove();
}
}
There is a built-in method to do that:
list1.removeAll(list2)
[EDIT]
You can create the lists easier using Arrays.asList:
List<String> list1 = new ArrayList<String>(Arrays.asList("INDIA", "JAPAN", "THAILAND", "MALAYSIA"));
List<String> list2 = Arrays.asList("THAILAND", "MALAYSIA");
list1.removeAll(list2);
[EDIT2]
The Arrays.asList produces unmodifiable list, so we have to use it to initialize a modifiable one.
[EDIT3]
Your code doesn't work because you don't advance the iterator. i.hasNext() only checks if there is a next element. It returns true or false, not the element itself. Here is how to fix this:
while (i.hasNext()) {
if (list2.contains(i.next())) {
i.remove();
}
}
You can also iterate over the list2 elements and remove them from list1:
for (String el : list2) {
list1.remove(el);
}

Connect linkedList in java [duplicate]

This question already has answers here:
Java Beginner: How do I link one linked list to another?
(6 answers)
Closed 8 years ago.
I hava list of LinkedList and I want to make (unable to modified) One connected LinkedList .
and not change the original linkedLists.
LinkedLists<String> a=new LinkedList<String>();
LinkedLists<String> b=new LinkedList<String>();
LinkedLists<String> c=new LinkedList<String>();
a.add("as");
a.add("sa");
a.add("bb");
b.add("as");
b.add("sa");
c.add("bb");
c.add("d");
c.add("ya");
the new LinkedList contain ya d bb sa as bb sa as
so I want to make one Linked List.I preffer Not copy the items casue this consume memory.
Only connect theme for go all over the items not to modified the items.
Thanks!
Try Collections#unmodifiableList()
Sample code:
LinkedList<String> a = new LinkedList<String>();
a.add("as");
a.add("sa");
a.add("bb");
a.add("as");
a.add("sa");
a.add("bb");
a.add("d");
a.add("ya");
List<String> b = Collections.unmodifiableList(a.subList(0, 3));
List<String> c = Collections.unmodifiableList(a.subList(5, 8));
b.set(0, "aa"); // not allowed
c.add("zz"); // not allowed
a.set(6, "zz"); // allowed and List c is also updated.
Try subclassing List. Here's a quick example I put together below. It's largely incomplete but you'll get the idea.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Experiment {
public static void main(String[] args) throws Exception {
LinkedList<String> a = new LinkedList<String>();
LinkedList<String> b = new LinkedList<String>();
LinkedList<String> c = new LinkedList<String>();
a.add("as");
a.add("sa");
a.add("bb");
b.add("as");
b.add("sa");
c.add("bb");
c.add("d");
c.add("ya");
MyLinkedList<String> list = new MyLinkedList<String>();
list.add(a);
list.add(b);
list.add(c);
for (String s : list) {
System.out.println(s);
}
}
private static class MyLinkedList<T> extends LinkedList<T> {
private List<List<T>> lists = new LinkedList<List<T>>();
public void add(LinkedList<T> list) {
lists.add(list);
}
#Override
public Iterator<T> iterator() {
return new MyLinkedIterator<T>(lists);
}
}
private static class MyLinkedIterator<T> implements Iterator<T> {
private List<List<T>> lists;
private int listIndex = 0;
private int currentIndex = 0;
private T next;
public MyLinkedIterator(List<List<T>> lists) {
this.lists = lists;
}
public boolean hasNext() {
if (listIndex >= lists.size()) return false;
List<T> list = lists.get(listIndex);
if (currentIndex >= list.size()) {
currentIndex = 0;
listIndex++;
return hasNext();
}
next = list.get(currentIndex++);
return true;
}
public T next() {
return next;
}
public void remove() {
}
}
}
How about this:
LinkedList<String> a=new LinkedList<String>();
LinkedList<String> b=new LinkedList<String>();
LinkedList<String> c=new LinkedList<String>();
a.add("as");
a.add("sa");
a.add("bb");
b.add("as");
b.add("sa");
c.add("bb");
c.add("d");
c.add("ya");
LinkedList<String> unionList = new LinkedList<String>();
unionList.addAll(a);
unionList.addAll(b);
unionList.addAll(c);
LinkedList<String> unmodifiableUnion = Collections.unmodifiableList(unionList);
It uses addAll() to add all lists into a new one and returns an unmodifiable list from it using Collections.unmodifiableList()
Update
If memory consumption is your problem, the standard JDK is not enough. You will have to implement your own or use an existing one.
To implement your own you can usa a LinkedList<List<T>> to store your linked lists and implement the List interface. mprivat started an implementation for you.
To use an existing one, you could use:
Trove: it is considered really good and fast if no fastest with least memory consumption, at least that is what I have observed in my usages of it.
this implementation: it is a singly linked list so it consumes less memory and has a merge method that will merge 2 linked lists using their "pointers" as you would expect.

Collections - clear()

I have created a collection and filled it with elements which are collections too, but when I tried to iterate through this container using a foreach construction (or other methods) it returns me nothing, I tried to get size() and saw what I expect (appropriate number) but seems like nevertheless container not empty inside each collection is null
Code snippet example:
Item it1, it2;
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
seq.add(it1);
hull.add(seq);
seq.clear();
seq.add(it2);
hull.add(seq);
for (<Collection<Item> c: hull)
System.out.println(c);
This is just an simplified snippet of what I do
Please suggest alternatives. Where did I make a mistake?
Each time you call seq.clear() you empty the inner ArrayList. Don't forget that when you add an object to a Collection, you only add the reference. You don't clone the Object. You should create a new ArrayList Object at each iteration.
E.g.
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
seq.add(it1);
hull.add(seq);
List<Item> seq2 = new ArrayList<Item>();
seq2.add(it2)
hull.add(seq2);
EDIT:
Complete Sample that compiles:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class NewClass1 {
static class Item {
String a;
public Item(String a) {
this.a = a;
}
#Override
public String toString() {
return a;
}
}
public static void main(String[] args) {
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
Item it1 = new Item("item 1");
seq.add(it1);
hull.add(seq);
List<Item> seq2 = new ArrayList<Item>();
Item it2 = new Item("item 2");
seq2.add(it2);
hull.add(seq2);
for (Collection<Item> current : hull) {
for (Item item : current) {
System.out.println(item);
}
}
}
}
Output:
run:
item 1
item 2
Your code, corrected to compile:
package sample;
import java.util.ArrayList;
import java.util.List;
public class Item {
public static void main( String[] args ) {
List< List< Item >> hull = new ArrayList<>();
List< Item > seq = new ArrayList<>();
seq.add( new Item());
hull.add( seq );
seq = new ArrayList<>(); // in place of seq.clear();
seq.add( new Item());
hull.add( seq );
for( List<Item> c: hull ) {
System.out.println( c.get( 0 ));
}
}
}
ouputs:
sample.Item#6da264f1
sample.Item#40914272
As you can see, there is no problem.
In order to iterate through a collection of collections you need a nested foreach.
for(Collection<Item> c: hull)
{
for(Item i: c)
{
}
}
By the way, are you aware that it1 and it2 are not initialized and that's why you are getting nothing?
size() will always give you the size of the collections, but they might be containing nulls (as it is your case).

Iterating a Collection more than once

I am having trouble using Iterator in java.
it=myHash.iterator();
while (it.hasNext())
if (it.next() satisfying something)
do something
while (it.hasNext())
if (it.next() satisfying something)
it.remove();
I am trying to iterate hashset twice, and the first loop making it.hasNext() return false. How to i resolve this?
I tried even adding the edit as you guys suggested, still not working...
You're reusing the same iterator - and that's been invalidated by adding new items to the set.
You should call iterator() again on the set:
it = set.iterator();
You can't reset the existing iterator
EDIT: Here's some sample code which shows this working:
import java.util.*;
public class Test {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("food");
set.add("bad");
set.add("hungry");
set.add("neighbour");
Iterator<String> it = set.iterator();
// Remove any string longer than 4
while (it.hasNext())
{
if (it.next().length() > 4)
{
it.remove();
}
}
set.add("new long text");
set.add("x");
// Remove any string shorter than 4
it = set.iterator();
while (it.hasNext())
{
if (it.next().length() < 4)
{
it.remove();
}
}
// Dump the results
for (String x : set)
{
System.out.println(x);
}
}
}
This gives the results "new long text" and "food".
Ideally, what you are looking for is a reset operation on an Iterator. Iterators are meant to be unidirectional and one-time use, as such they don't have support for reset in Java.
You can either get hold of a new Iterator instance or use ListIterator interface which allows you to look backwards using previous().
Edit:
You are using remove() on the iterator which is also removing elements from the original set. In such a case you should consider making a copy of the set since you want to iterate over the elements all over again:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorSnippet {
public static void main(String[] args) {
final HashSet<Integer> myHash = new HashSet<Integer>();
myHash.addAll(Arrays.asList(1, 2, 3, 4, 5));
// make copy before using iterator with remove
final HashSet<Integer> myHash2 = new HashSet<Integer>(myHash);
Iterator<Integer> it = myHash.iterator();
System.out.println("First go...");
while (it.hasNext()) {
System.out.println(it.next());
it.remove();
}
it = myHash2.iterator();
System.out.println("Second go...");
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

Categories

Resources