This is more of a conceptual question about how to most efficiently approach this issue, I'm utilizing LinkedLists created in a form I recently learned in class. I'll paste in both the node class I created as well as the LinkedList class itself. As I have the code set up now, I can only create lists with a single data type, in this instance being BufferedImages, but I want to be able to create one LinkedList for a BufferedImage and another for an int. Is there a better way to do this than making separate Node and LinkedList classes for each data type or overloading each class?
I want to be able to efficiently have two LinkedList objects storing different data types
//Node class:
import java.awt.image.BufferedImage;
public class Node {
private BufferedImage data;
private Node link;
public Node getLink() {
return link;
}
public void setLink(Node link){
this.link = link;
}
public BufferedImage getData(){
return data;
}
public void setData(BufferedImage data) {
this.data = data;
}
}
//LinkedList class:
import java.awt.image.BufferedImage;
public class LinkedList {
private Node root;
public Node getRoot(){
return root;
}
public void add(BufferedImage data) {
if (root == null) {
root = new Node();
root.setData(data);
} else {
Node tmp = root;
while (tmp.getLink() != null) {
tmp = tmp.getLink();
}
Node n = new Node();
n.setData(data);
tmp.setLink(n);
}
}
public int size() {
if (root == null) {
return 0;
}
int count = 0;
Node tmp = root;
while (tmp != null) {
count++;
tmp = tmp.getLink();
}
return count;
}
public BufferedImage get(int pos) {
if (pos < 0 || pos >= size()) {
throw new IndexOutOfBoundsException("The index " + pos + " is out of bounds.");
}
Node tmp = root;
for (int i = 0; i < pos; i++) {
tmp = tmp.getLink();
}
return tmp.getData();
}
public void set(int pos, BufferedImage data) {
if (pos < 0 || pos >= size()) {
throw new IndexOutOfBoundsException("The index " + pos + " is out of bounds.");
}
Node tmp = root;
for (int i = 0; i < pos; i++) {
tmp = tmp.getLink();
}
tmp.setData(data);
}
//DELETES LAST DATA
public void delete(){
if(root != null){
Node tmp = root;
for(int i=0; i < size()-2; i++){
tmp = tmp.getLink();
}
tmp.setLink(null);
}
}
}
As I find the baeldung article nod sufficient enough for beginners, I quickly re-wrote your code to support generics.
In simple terms, instead of giving Node a fixed content like BufferedImage
, we introduce our own type parameter. Usually that is simply called <T>
, but here I go with <MyGenericType>
to show that it can be handled like any other type.
The little downside is that we have to explicitly type Node<MyGenericType>
wherever we use it, so this makes the code a bit longer.
package stackoverflow.linkedlist;
public class Node<MyGenericType> {
private MyGenericType data;
private Node<MyGenericType> link;
public Node<MyGenericType> getLink() {
return link;
}
public void setLink(final Node<MyGenericType> link) {
this.link = link;
}
public MyGenericType getData() {
return data;
}
public void setData(final MyGenericType data) {
this.data = data;
}
}
Same here, introduce generics
package stackoverflow.linkedlist;
public class LinkedList<MyGenericType> {
private Node<MyGenericType> root;
public Node<MyGenericType> getRoot() {
return root;
}
public void add(final MyGenericType data) {
if (root == null) {
root = new Node<>();
root.setData(data);
} else {
Node<MyGenericType> tmp = root;
while (tmp.getLink() != null) {
tmp = tmp.getLink();
}
final Node<MyGenericType> n = new Node<>();
n.setData(data);
tmp.setLink(n);
}
}
public int size() {
if (root == null) {
return 0;
}
int count = 0;
Node<MyGenericType> tmp = root;
while (tmp != null) {
count++;
tmp = tmp.getLink();
}
return count;
}
public MyGenericType get(final int pos) {
if (pos < 0 || pos >= size()) {
throw new IndexOutOfBoundsException("The index " + pos + " is out of bounds.");
}
Node<MyGenericType> tmp = root;
for (int i = 0; i < pos; i++) {
tmp = tmp.getLink();
}
return tmp.getData();
}
public void set(final int pos, final MyGenericType data) {
if (pos < 0 || pos >= size()) {
throw new IndexOutOfBoundsException("The index " + pos + " is out of bounds.");
}
Node<MyGenericType> tmp = root;
for (int i = 0; i < pos; i++) {
tmp = tmp.getLink();
}
tmp.setData(data);
}
//DELETES LAST DATA
public void delete() {
if (root != null) {
Node<MyGenericType> tmp = root;
for (int i = 0; i < size() - 2; i++) {
tmp = tmp.getLink();
}
tmp.setLink(null);
}
}
}
Here I show you how to use the list. As you can see, we now have to define/introduce the 'concept' (aka Type) of BufferedImage from the outside, when we tell our list what type it should handle: LinkedList<BufferedImage> imageList = new LinkedList<>();
package stackoverflow.linkedlist;
import java.awt.image.BufferedImage;
public class Usage {
public static void main(final String[] args) {
final LinkedList<BufferedImage> imageList = new LinkedList<>();
final BufferedImage bi1 = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
final BufferedImage bi2 = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
imageList.add(bi1);
imageList.add(bi2);
System.out.println("Size of image list is now: " + imageList.size());
final LinkedList<Integer> intList = new LinkedList<>();
intList.add(Integer.valueOf(667));
intList.add(Integer.valueOf(668));
intList.add(Integer.valueOf(669));
System.out.println("Size of Integer is now: " + intList.size());
final LinkedList<DemoCombo> mixedList = new LinkedList<>();
mixedList.add(new DemoCombo(bi1, 667));
mixedList.add(new DemoCombo(bi2, 668));
System.out.println("Size of mixed list is now: " + mixedList.size());
}
static private class DemoCombo {
public final BufferedImage image;
public final int value;
public DemoCombo(final BufferedImage pImage, final int pValue) {
image = pImage;
value = pValue;
}
}
}
I also included the DemoCombo class, because I was unsure why you wanted to have a list of BufferedImage and one of int. Normally, if you have data that is related, like BufferedImage has a direct relation to the int, you should not have 2 different lists to store them in. In this case, it's a lot better to write a simple wrapper class, DemoCombo, so all data that belongs to each other is always together, and you do not have the pitfalls of having to manage 2 lists independently.