Connect linkedList in java [duplicate] - java

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.

Related

Unique set from ArrayList of ArrayList

Hi I have an arraylist of arraylist in this format:
[[val1, val2],[val3,val4],[val1,val2],[val1,val5]]
and would like to get the unique set of arraylists:
[[val1, val2],[val3,val4],[val1,val5]]
I have tried the following:
Set<String> uniques = new HashSet<>();
for (ArrayList<String> sublist : mappedEntities) {
uniques.addAll(sublist);
}
but this merges all the values of the internal arraylist together
can use Java 8 Collection Stream Distinct,
return in Set datatype :
Set<List<String>> uniques = mappedEntities.stream().distinct().collect(Collectors.toSet());
if you want return in List :
List<List<String>> uniques = mappedEntities.stream().distinct().collect(Collectors.toList());
Why not simply put them in a Set like this?
Set<List<String>> uniques = new HashSet<>(mappedEntities);
Your mistake is that you are flattening the inner lists and putting their items in the set separately.
The issue here is that you need a Set of ArrayList Set<ArrayList<String>>, but you are using a Set of Strings Set<String> instead.
Given the list :
List<List<String>> mappedEntities = Arrays.asList(Arrays.asList("val1", "val2"),
Arrays.asList("val3", "val4"),
Arrays.asList("val1", "val2"),
Arrays.asList("val1", "val5"));
All you need to do is just declare the set and use the addAll().
Set<List<String>> mySet = new HashSet<>();
mySet.addAll(mappedEntities);
Since a set can hold only unique values, all duplicates will not be added to the set (No need to explicitly check this). You can now print it out :
mySet.forEach(System.out::println);
Or more simply, initialize the HashSet using the list mappedEntities :
Set<List<String>> mySet = new HashSet<>(mappedEntities);
I am beginner on STACKOVERFLOW but i to try solve your problem
I think you want like this..
import java.util.*;
public class GFG {
public static void main(String[] args)
{
int n = 3;
// Here aList is an ArrayList of ArrayLists
ArrayList<ArrayList<String> > aList =
new ArrayList<ArrayList<String> >(n);
// Create n lists one by one and append to the
// master list (ArrayList of ArrayList)
ArrayList<String> a1 = new ArrayList<String>();
a1.add("1");
a1.add("2");
aList.add(a1);
ArrayList<String> a2 = new ArrayList<String>();
a2.add("11");
a2.add("22");
aList.add(a2);
ArrayList<String> a3 = new ArrayList<String>();
a3.add("1");
a3.add("2");
aList.add(a3);
Set<ArrayList<String>> uniques = new HashSet<ArrayList<String>>();
for (ArrayList<String> sublist : aList) {
uniques.add(sublist);
}
System.out.println("Your Answer");
for (ArrayList<String> x : uniques)
System.out.println(x);
}
}
try this code:
public class B {
public static void main(String[] args) throws Exception {
List<List<String>> list= Arrays.asList(
Arrays.asList("a","b","c"),
Arrays.asList("a","b","c"),
Arrays.asList("a","b","c","d"));
Set<List<String>> uniques = new HashSet<>();
for (List<String> sublist : list) {
if(!uniques.contains(sublist))
uniques.add(sublist);
}
System.out.println(uniques);
}
}
output:
[[a, b, c], [a, b, c, d]]

Arraylist of arrays

I have two arraylists
ArrayList<File> filesImage= new ArrayList<File>();
ArrayList<File> filesBox= new ArrayList<File>();
I want to merge into third arraylist like this
ArrayList<File[]> combinedFiles=new ArrayList<File[]>();
How can I do this?
Output should be like:
[[ first object of filesImage, first object of filesBox],[second Object],[]]
Given that the two arrays are of equal length that you wish to combine, i'd personally do something like this.
List<File[]> combinedFiles= new ArrayList<File[]>();
for(int i = 0; i < filesBox.size(); i++){
combinedFiles.add(new File[] {filesImage.get(i), filesBox.get(i)});
}
Apologies if my methods are incorrect, its been a while since i've programmed in java.
First, I'd create a class that holds the file references, e.g. like this:
class FileElement {
File image;
File box;
}
Then I'd create a list of those instead of arrays:
List<FileElement> combinedFiles = ...;
Then I'd iterate over both lists simultaneously:
Iterator<File> imgItr = filesImages.iterator();
Iterator<File> boxItr = filesBox.iterator();
//This assumes it's ok if both lists have different sizes.
//If it isn't you could try && instead, i.e. stop once you'd miss an image or a box
while( imgItr.hasNext() || boxItr.hasNext() ) {
FileElement e = ...;
if( imgItr.hasNext() ) {
e.image = imgItr.next();
}
if( boxItr.hasNext() ) {
e.box= boxItr.next();
}
combinedFiles.add( e );
}
Assuming that the two lists are of equal length, here is a solution using Java8 streams and zip().
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Demo {
public static void main( String[] args ) {
List<String> filesImage = Arrays.asList("a","b","c");
List<String> filesBox = Arrays.asList("1","2", "3");
List<String[]> result = zip(filesImage.stream(), filesBox.stream(), (a,b) -> new String[] {a,b}).collect( Collectors.toList() );
for ( String[] e : result ) {
System.out.println( Arrays.asList(e) );
}
}
public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
final Iterator<A> iteratorA = streamA.iterator();
final Iterator<B> iteratorB = streamB.iterator();
final Iterator<C> iteratorC = new Iterator<C>() {
#Override
public boolean hasNext() {
return iteratorA.hasNext() && iteratorB.hasNext();
}
#Override
public C next() {
return zipper.apply(iteratorA.next(), iteratorB.next());
}
};
final boolean parallel = streamA.isParallel() || streamB.isParallel();
return iteratorToFiniteStream(iteratorC, parallel);
}
public static <T> Stream<T> iteratorToFiniteStream( Iterator<T> iterator, boolean parallel) {
final Iterable<T> iterable = () -> iterator;
return StreamSupport.stream(iterable.spliterator(), parallel);
}
}
I borrowed the implementation of zip from Karol Krol here. Zip is the name from the functional world for this pattern of combining two lists in this manner. Also note that while Demo uses String's instead of File, the concept remains exactly the same.
Normally I wouldn't answer a question where OP doesn't show what they've tried, but since I'm seeing a flood of incorrect answers and interpretations...
List<File> filesImage= new ArrayList<File>();
List<File> filesBox= new ArrayList<File>();
List<File[]> combinedFiles=new ArrayList<File[]>();
for (int i = 0; i < filesImage.size(); ++i) {
File[] temp = new File[2];
temp[0] = filesImage.get(i);
temp[1] = filesBox.get(i);
combinedFiles.add(temp);
}
Something like this is known as "zipping" in functional programming, by the way. I'd suggest a solution with Java 8 lambdas, but there doesn't seem to be a zip function in Java SE and the above is quite simple.
Should work similar to this pseudo code
List<File[]> merge = new ArrayList<>();
for(int i=0;i<filesImage.legth&&i<filesBox.length;i++{
merge.add(new File[]{i<filesImage.legth?filesImage[i]:null,i<filesBox.legth?filesBox[i]});
}
You can use function toArray of List to make array.
ArrayList<File> filesImage= new ArrayList<File>();
ArrayList<File> filesBox= new ArrayList<File>();
ArrayList<File[]> combinedFiles=new ArrayList<File[]>();
//add content to 2 lists here
File[] arrayFiles;
//add array image
arrayFiles = new File[filesImage.size()];
arrayFiles = filesImage.toArray(arrayFiles);
combinedFiles.add(arrayFiles);
//add array box
arrayFiles = new File[filesBox.size()];
arrayFiles = filesBox.toArray(arrayFiles);
combinedFiles.add(arrayFiles);
System.out.println(combinedFiles);

Implementing a Graph using a HashMap

I'm new to Java, so please keep that in mind before getting trigger happy down-voting. I'm familiar with the popular implementation of a graph of integers using an array.
Graph{
int vertices;
LinkedList<Integer>[] adj;
Graph(int vertices){
this.vertices = vertices;
adj = new LinkedList<>();
for(int i= 0; i <vertices; i++){
adj[i] = new LinkedList();
}
}
However this implementation is best suited to a graph of integers.
In case I want to implmentation graph of Characters, this implemetation doesn't render itself directly usable.
So I tried implementing using a HashMap.
public class Graph {
int vertices;
HashMap<Character, LinkedList<Character>> adj;
Graph(int item){
this.vertices = item;
adj = new HashMap<>();
}
}
Where I'm a little stuck syntactically with Java is adding keys and values to this HashTable. What I'm trying to do is implement this method.
public void add(Character a, Character b){
if (adj.containsKey(a)){
//get a reference to the existing linked list
//add to the existing LinkedList
}else{
//create a new LinkedList and add to it.
}
}
}
I could use some help with the incomplete add method as also how to iterate through the this adj HashMap once the graph is constructed.
Since your question is only about syntax, you can do something like this:
public void add(Character a, Character b){
if (adj.containsKey(a)){
//get a reference to the existing linked list
LinkedList<Character> l = adj.get(a);
//add to the existing LinkedList
//You need to do a null check here to make sure (l != null)
l.add(b)
}else{
//create a new LinkedList and add to it.
LinkedList<Character> l = new LinkedList<Character>();
l.add(b);
adj.put(a, l);
}
}
}
HashMap stores the node number as key and the list of all the adjacent nodes as value. The list has been implemented using LinkedList class. Just change the class of Key and value according to your requirement.
class Graph{
HashMap<Integer,LinkedList<Integer>> map = new HashMap<>();
//add an edge from source to destination
void addEdge(int src, int dest){
if(!map.containsKey(src)){
LinkedList<Integer> l= new LinkedList<>();
l.add(dest);
map.put(src,l);
}
else{
LinkedList<Integer> l= map.get(src);
l.add(dest);
map.put(src,l);
}
}
//display the adjency list
void displayGraph(){
for(Map.Entry m: map.entrySet()){
System.out.println(m.getKey()+"-->"+m.getValue());
}
}
public static void main(String[] args) {
Graph g= new Graph();
g.addEdge(0,1);
g.addEdge(0,4);
g.addEdge(0,5);
g.addEdge(1,4);
g.addEdge(1,3);
g.addEdge(3,2);
g.addEdge(2,1);
g.addEdge(3,4);
g.displayGraph();
}
}
Output:
0-->[1, 4, 5]
1-->[4, 3]
2-->[1]
3-->[2, 4]

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).

Why doesn't Java allow "new List<T>"?

To create a List, why doesn't Java allow them to be created then elements added one by one?
This works:
public static List<TrackedItem> create(List<Item> items)
{
TrackedItem[] arr = new TrackedItem[items.size()];
int i = 0;
for (Item item : items)
{
arr[i] = TrackedItem.createOrUpdate(item);
i++;
}
return java.util.Arrays.asList(arr);
}
This does not work (tracked.add() causes a NullPointerException):
public static List<TrackedItem> create(List<Item> items)
{
List<TrackedItem> tracked = java.util.Collections.emptyList();
for (Item item : items)
{
tracked.add(TrackedItem.createOrUpdate(item));
}
return tracked;
}
java.util.Collections.emptyList();
static
List
emptyList()
Returns the empty list (immutable).
That means, you will not be able to change this list.
Its defined:
static List EMPTY_LIST
The empty list (immutable).
Quotes from Java sun reference
Edit:
To create a new list you could use e.g.
List myList = new ArrayList<MyClass>();
Use the following syntax:
public static List<TrackedItem> create(List<Item> items)
{
List<TrackedItem> tracked = new ArrayList<TrackedItem>();
for (Item item : items)
{
tracked.add(TrackedItem.createOrUpdate(item));
}
return tracked;
}
This might be a misunderstanding.
Even if it is called emptyList, it isn't a list which is just empty and ready to be populated. This emptyList is designed to be empty at all times. You can't add to this special list.
To get a 'usable' empty list you can either
List<String> list = new ArrayList<String>(); // create a new one or
list.add("if you have an list");
list.clear(); // just clear it
create a new arrayList by :
List<T> tracked = new ArrayList<T>();
List is only an interface ... you can't make a new one. you only can implement it.

Categories

Resources