Emulating a linked list in Java [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
Is it possible to emulate a linked list in java by nesting a class within a class? I have tried to implement, but the summation function doesn't move passed the first class. This generates a 1 no matter what integer it is given:
public class Example {
static class Item{
boolean b;
double d;
Item nextItem;
Item (boolean b, double d, Item nextItem) {
this.b = b;
this.d = d;
this.nextItem = nextItem;
}
}
static double f(Item item) {
if(item != null)
return (item.b ? item.d : 0.0) + f(item.nextItem);
else
return 0.0;
}
static public void main(String args[]) {
int n = Integer.parseInt(args[0]);
Item firstItem = null;
firstItem = new Item((1%2!= 0), Math.sqrt(1), null);
if(n > 1){
Item nextItem = firstItem.nextItem;
for (int i = 2; i <= n; i++) {
nextItem = new Item((i%2!=0), Math.sqrt(i), null);
nextItem = nextItem.nextItem;
}
}
double s = f(firstItem);
System.out.println("sum = " + s);
}
}

Of course you can implement a LinkedList using nested classes. There are many ways to do it. Here you have an example: LinkedList example
But the problem you have is the variable firstItem never change. You assing the value here:firstItem = new Item((1%2!= 0), Math.sqrt(1), null);
and then you loop another variable Item nextItem = firstItem.nextItem; that is always null.
Remove the argument nextItem of constructor if you alaways set it to null.

Related

Best way of calculating permutations [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to figure out the best way of finding/automating all the possible permutations for a certain scenario.
I have a program which takes in a set of numbers [X, Y , Z], Each number has a predefined uncertainty. Therefore, I want to run my program against [X, Y , Z], [X+e, Y, Z] [x-e, Y, Z], [X, Y+e, Z] etc. Right now I have built an object which contains all the 27 possibilities and I'm iterating through it in order to provide my program with a new set of input. (I'll run my program 27 times with different set of inputs)
as time goes, I'd need to update my program to take in a bigger set of numbers. So I'm wondering whether there is a better way of calculating all the possible permutations my base set may have.
I'd rather know the way of implementing this instead of using any existing libraries (if there is any). I see this as a learning program. Thanks!
Instead of writing down the the 3x3x3 sets of 3 numbers by hand, you can use nested loops. If you have 3 loops, one inside the other, each running 3 times, you get 27 outputs:
double[] numbers = new double[3];
double[] e = {-1e-6, 0, 1e-6};
for (double eX : e) {
for (double eY : e) {
for (double eZ : e) {
double[] newNumbers = {numbers[0] + eX, numbers[1] + eY, numbers[2] + eZ};
// Run your program using "newNumbers". Just as an example:
System.out.println(Arrays.toString(newNumbers));
}
}
}
As for
as time goes, I'd need to update my program to take in a bigger set of numbers
If the size of the set is going to be small and fixed, you can just add more nested loops. If not, you are going to need more advanced techniques .
Here is a permutation method I found some time ago. It prints them within the method. It only does single dimension permutations but you may be able to adapt it to your needs.
public static void generate(int n, int[] a) {
if (n == 1) {
System.out.println(Arrays.toString(a));
} else {
for (int i = 0; i < n - 1; i++) {
generate(n - 1, a);
if ((n & 1) == 0) {
swap(i, n - 1, a);
} else {
swap(0, n - 1, a);
}
}
generate(n - 1, a);
}
}
public static void swap(int a, int b, int[] array) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
I believe the best way to do this is to implement a Spliterator and wrap it in a Stream:
public interface Combinations<T> extends Stream<List<T>> {
public static <T> Stream<List<T>> of(Collection<T> collection) {
SpliteratorSupplier<T> supplier =
new SpliteratorSupplier<T>(collection);
return supplier.stream();
}
...
}
Which solves the general use-case:
Combinations.of(List.of(X, Y, Z)).forEach(t -> process(t));
Implementing the Spliterator is straightforward but tedious and I have written about it here. The key components are a DispatchSpliterator:
private Iterator<Supplier<Spliterator<T>>> spliterators = null;
private Spliterator<T> spliterator = Spliterators.emptySpliterator();
...
protected abstract Iterator<Supplier<Spliterator<T>>> spliterators();
...
#Override
public Spliterator<T> trySplit() {
if (spliterators == null) {
spliterators = Spliterators.iterator(spliterators());
}
return spliterators.hasNext() ? spliterators.next().get() : null;
}
#Override
public boolean tryAdvance(Consumer<? super T> consumer) {
boolean accepted = false;
while (! accepted) {
if (spliterator == null) {
spliterator = trySplit();
}
if (spliterator != null) {
accepted = spliterator.tryAdvance(consumer);
if (! accepted) {
spliterator = null;
}
} else {
break;
}
}
return accepted;
}
A Spliterator for each prefix:
private class ForPrefix extends DispatchSpliterator<List<T>> {
private final int size;
private final List<T> prefix;
private final List<T> remaining;
public ForPrefix(int size, List<T> prefix, List<T> remaining) {
super(binomial(remaining.size(), size),
SpliteratorSupplier.this.characteristics());
this.size = size;
this.prefix = requireNonNull(prefix);
this.remaining = requireNonNull(remaining);
}
#Override
protected Iterator<Supplier<Spliterator<List<T>>>> spliterators() {
List<Supplier<Spliterator<List<T>>>> list = new LinkedList<>();
if (prefix.size() < size) {
for (int i = 0, n = remaining.size(); i < n; i += 1) {
List<T> prefix = new LinkedList<>(this.prefix);
List<T> remaining = new LinkedList<>(this.remaining);
prefix.add(remaining.remove(i));
list.add(() -> new ForPrefix(size, prefix, remaining));
}
} else if (prefix.size() == size) {
list.add(() -> new ForCombination(prefix));
} else {
throw new IllegalStateException();
}
return list.iterator();
}
}
and one for each combination:
private class ForCombination extends DispatchSpliterator<List<T>> {
private final List<T> combination;
public ForCombination(List<T> combination) {
super(1, SpliteratorSupplier.this.characteristics());
this.combination = requireNonNull(combination);
}
#Override
protected Iterator<Supplier<Spliterator<List<T>>>> spliterators() {
Supplier<Spliterator<List<T>>> supplier =
() -> Collections.singleton(combination).spliterator();
return Collections.singleton(supplier).iterator();
}
}

Remove duplicates from an arraylist with strings

I have an arraylist that looks like this:
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
I store groups of 2 persons in a pair. For example:
[Person1, Person2]
[Person3, Person4]
The algorithm I use right now still makes duplicates, I've tried out hashmaps and iterating through them with for loop but they just give me back the original list.
This is the code:
package com.company;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class createGroups
{
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
public static void main(String[] args){
//Define names
String[] names = {"Person1", "Person2", "Person3", "Person4"};
try
{
//Create combinations. In a try catch because of the saveFile method.
combination(names, 0, 2);
//Print all the pairs in the Arraylist x
printPairs();
} catch (IOException e)
{
e.printStackTrace();
}
}
static void combination(String[] data, int offset, int group_size) throws IOException
{
if(offset >= data.length)
{
//Create new Arraylist called foo
ArrayList<String[]> foo = new ArrayList<>();
//Create a pair of 2 (data.length = 4 / group_size = 2)
for(int i = 0; i < data.length / group_size; i++)
{
//Add the pair to foo.
foo.add(Arrays.copyOfRange(data, 2 * i, 2 * (i + 1)));
}
//Add foo to x
x.add(foo);
//saveFile(foo);
}
for(int i = offset; i < data.length; i++){
for(int j = i + 1; j < data.length; j++){
swap(data, offset, i);
swap(data, offset + 1, j);
combination(data, offset + group_size, group_size);
swap(data, offset + 1, j);
swap(data, offset, i);
}
}
}
public static void printPairs(){
//Print all pairs
for(ArrayList<String[]> q : x){
for(String[] s : q){
System.out.println(Arrays.toString(s));
}
System.out.println("\n");
}
}
private static void swap(String[] data, int a, int b){
//swap the data around.
String t = data[a];
data[a] = data[b];
data[b] = t;
}
}
The output right now is this:
Output
Every group of 4 names is a 'list' of pairs (Not really a list but that's what I call it)
And this is the desired output:
Desired output
But then you can see that the first and the last list of pairs are basically the same how do I change that in my combination method
The question:
How can I change my combination method so that it doesn't create duplicate groups.
And how can I make the list smaller (The desired output) when printing the created lists.
If I wasn't clear enough or if I didn't explain what I want very well, let me know. I'll try to make it clearer.
Create an object similar to this. It takes 4 strings (2 pairs). Puts the strings into array and sorts this array. That means any combination of strings you put in will be converted into one sorted combination, but the object internaly remembers which person is person1, person2, ...
private class TwoPairs {
private final String person1;
private final String person2;
private final String person3;
private final String person4;
private final String[] persons;
TwoPairs(String person1, String person2, String person3, String person4) {
this.person1 = person1;
this.person2 = person2;
this.person3 = person3;
this.person4 = person4;
persons = new String[4];
persons[0] = person1;
persons[1] = person2;
persons[2] = person3;
persons[3] = person4;
// if we sort array of persons it will convert
// any input combination into single (sorted) combination
Arrays.sort(persons); // sort on 4 objects should be fast
// hashCode and equals will be comparing this sorted array
// and ignore the actual order of inputs
}
// compute hashcode from sorted array
#Override
public int hashCode() {
return Arrays.hashCode(persons);
}
// objects with equal persons arrays are considered equal
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
TwoPairs other = (TwoPairs) obj;
if (!Arrays.equals(persons, other.persons)) return false;
return true;
}
// add methods which you might need
// getters for individual persons
// String getPerson1() { return person1; }
// or perhaps pairs of persons
// String[] getPair1() { return new String[] {person1, person2}; }
// add sensible toString method if you need it
}
Your ArrayList x will change like this
ArrayList<TwoPairs> x = new ArrayList<TwoPairs>();
before adding new TwoPairs object into x check if this list already contains this object.
if (!x.contains(twoPairsObject)) {
x.add(twoPairsObject);
}

Why are all elements in my array of objects null? [duplicate]

This question already has answers here:
Initializing an array in Java using the 'advanced' for each loop [duplicate]
(5 answers)
Closed 5 years ago.
I have 2 classes. The first describes an item, and the seconds is built around an array of items of the first class.
I had learned that just creating an array of objects doesn't initialize them. So I put a for-loop in the constructor of the 2nd class to initialize all items.
Yet when entering the clear() function, all elements of the list array are still null. Why is that?
class HneAnalogItem {
String description;
String unit;
float value;
HneAnalogItem(){}
}
class HneAnalogInfo
{
static final private int MAXANALOGINFOITEMS = 100;
private HneAnalogItem[] list;
HneAnalogInfo() {
list = new HneAnalogItem[MAXANALOGINFOITEMS];
for(HneAnalogItem item : list) {
item = new HneAnalogItem();
}
clear();
}
void clear() {
for(HneAnalogItem item : list) {
item.description = "";
item.unit = "";
item.value = 0;
}
}
}
for (HneAnalogItem item : list) {
item = new HneAnalogItem();
}
This enhanced for loop doesn't initialize the array elements. It is equivalent to:
for (int i = 0; i < list.length; list++) {
HneAnalogItem item = list[i];
item = new HneAnalogItem();
}
To initialize the array elements you need:
for (int i = 0; i < list.length; list++) {
list[i] = new HneAnalogItem();
}

Is it not possible to have an array based Queue with generics ? [duplicate]

This question already has answers here:
How to create a generic array in Java?
(32 answers)
Closed 7 years ago.
This is an array based Queue , for int :
/**
* Array based
* #author X220
*
*/
public class MyQueue {
private int[] _data;
private int MAX_SIZE;
private int front = -1;
private int back = 0;
private int elementsCount = 0;
public void printQueue()
{
int j = this.front + 1;
int i = 0;
while (i < this._data.length && i < elementsCount)
{
System.out.println("At location " + j % MAX_SIZE + " element :" + this._data[j % MAX_SIZE]);
j++;
i++;
}
}
public MyQueue(int _size)
{
MAX_SIZE = _size > 0 ? _size : 10;
this._data = new int[MAX_SIZE];
}
public boolean IsEmpty()
{
return this.elementsCount == 0;
}
public boolean IsFull()
{
return this.elementsCount == MAX_SIZE;
}
public void Push(int pushMe) throws QueueIsFullException
{
if (IsFull())
{
throw new QueueIsFullException("Queue is full");
}
this.elementsCount++;
_data[back++ % MAX_SIZE] = pushMe;
}
public int Pop() throws QueueIsEmptyException
{
if (IsEmpty())
{
throw new QueueIsEmptyException("Queue is full");
}
elementsCount--;
return _data[++front % MAX_SIZE];
}
public static void main(String args[])
{
try
{
MyQueue q1 = new MyQueue(15);
q1.Push(1);
q1.Push(2);
q1.Push(3);
q1.Push(4);
q1.Push(5);
q1.Pop();
q1.Pop();
q1.Pop();
q1.Pop();
q1.Pop();
q1.Push(6);
q1.Pop();
q1.Push(7);
q1.Push(8);
q1.Push(9);
q1.Push(10);
q1.Push(11);
q1.Push(12);
// q1.Push(1);
// q1.Push(2);
// q1.Push(3);
// q1.Push(4);
// q1.Push(5);
// q1.Push(7);
// q1.Push(8);
// q1.Push(9);
// q1.Push(10);
// q1.Push(11);
// q1.Push(12);
// q1.Push(40);
// q1.Push(50);
q1.printQueue();
}
catch (Exception e)
{
System.out.println(e);
}
}
#SuppressWarnings("serial")
class QueueIsFullException extends Exception
{
public QueueIsFullException(String message){
super(message);
}
}
#SuppressWarnings("serial")
class QueueIsEmptyException extends Exception
{
public QueueIsEmptyException(String message){
super(message);
}
}
}
I wanted to use generics so I changed the int to T but then I got for this :
public class MyQueue <T>{
private T[] _data;
private int MAX_SIZE;
private int front = -1;
private int back = 0;
private int elementsCount = 0;
public void printQueue()
{
int j = this.front + 1;
int i = 0;
while (i < this._data.length && i < elementsCount)
{
System.out.println("At location " + j % MAX_SIZE + " element :" + this._data[j % MAX_SIZE]);
j++;
i++;
}
}
public MyQueue(int _size)
{
MAX_SIZE = _size > 0 ? _size : 10;
this._data = new T[MAX_SIZE];
}
....
}
That :
Cannot create a generic array of T
And from the answers to this post I see that I can't use generics with arrays .
Does this mean that there is no work around for a generics Queue based on array ? Must I switch to some other data structure ?
The root cause of your problem is not with your MyQueue class, I think you misunderstand the way Java handles generics. Generic types exist only at compile time, after that they are simply erased from the byte code and at runtime only real Java types exist behind the scenes.
This is why you cannot instantiate a generic type, because at runtime this parameterized type simply doesn't exist.
What you can do is to provide a real class (extending T) as a parameter in your MyQueue class an instantiate this class type, since this is a first-class Java type.
Here is a very similar StackOverflow question and a solution:
Instantiating a generic class in Java
It is also recommended to read the Java reference about generics, like the answer for you original question is here:
https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createObjects
No there is a work around for this the ugly cast, change your array generic creation to:
this._data = (T[])new Object[MAX_SIZE];
Due to the implementation of Java generics, you can't have code like this:
this._data = new T[MAX_SIZE];
Have a look at this How to create a generic array in Java?
The method I prefer is using
#SuppressWarnings("unchecked")
T[] arr = (T[]) Array.newInstance(clazz,length);
where clazz is the Class<T> object corresponding to the generic type. Note that the cast is unchecked, but Array.newInstance ensures you that you won't be able to insert invalid types into your array.
To me this is the best solution because :
you handle the type consistency to the Array class by passing a Class<T> instance which will be used to cast all the objects inserted in the array. This is thus type-safe without needing you to do anything.
this is relatively small and self-contained, it won't force you to manually cast objects over and over everytime you use the array. This would be the case if you were using an Object[] under the hood.

Creating unique random numbers

I have created the following method so as to create unique random numbers . (This unique values belong to the nodes of a tree):
static Random rand = new Random();
public static ArrayList<Node> go(int n) {
ArrayList<Node> list = new ArrayList<Node>();
ArrayList<Integer> numList = new ArrayList<Integer>();
// TODO Auto-generated method stub
for(int i = 1; i<=5; i++)
{
int number = rand.nextInt(10)+1;
if(list.size()>0 && !check(list,number))
{
i--;
continue;
}
numList.add(number);
Node node = new Node();
node.data = number;
list.add(node);
}
int w = 0;
for (Node d : list) {
System.out.println(w+": "+d.data);
w++;
}
return list;
}
private static boolean check(ArrayList<Node> list, int num) {
// TODO Auto-generated method stub
boolean b = false;
/*if(list.size()==0)
return true;
*/
for (Node node : list) {
if(node.data == num)
b = false;
else
b = true;
}
return b;
}
But it doesn’t create unique numbers and there are still duplicates in my list. Like :
0: 10
1: 1
2: 10
3: 5
4: 6
The problem is that you don't stop the for loop inside the check function if it finds a duplicated number. The loop continues and b can change back to true.
What you should do is for example:
private static boolean check(ArrayList<Node> list, int num) {
for (Node node : list) {
if(node.data == num)
return false;
}
return true;
}
Jón Trausti Arason has your answer, but...
Since you have a finite number of allowed values (integers), and since you don't want the same one picked more than once, perhaps it would be easier to just shuffle an array of the allowed values. Then you could just pick off the next value from the array and not worry about checking every time whether it's a repeat.
In your example selecting five values between one and ten, you could start with an array {1,2,3,4,5,6,7,8,9,10} and run it through a shuffle to rearrange it to something else like {3,4,7,1,10,9,5,8,2,6}. Take the first five values out of that resulting array with no worries about repeats.
In your check method, this looks a bit dodgy:
if (node.data == num)
b = false;
else
b = true
Surely once you've found a match (e.g. b = false) you want to return? Otherwise the next time around the loop b might be set to true. To simplify a bit, if you want to check whether an item is in a collection you can do list.contains(element)
You "forget" to use the numList that you've prepared.
This code should work fine:
static Random rand = new Random();
public static ArrayList<Node> go(int n) {
ArrayList<Node> list = new ArrayList<Node>();
ArrayList<Integer> numList = new ArrayList<Integer>();
for (int i = 1; i <= 5; i++) {
int number = rand.nextInt(10) + 1;
if (numList.contains(number)) {
i--;
continue;
}
numList.add(number);
Node node = new Node();
node.data = number;
list.add(node);
}
int w = 0;
for (Node d : list) {
System.out.println(w + ": " + d.data);
w++;
}
return list;
}
To illustrate on #eaj's point.
public static List<Node> go(int n) {
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) numbers.add(i);
Collections.shuffle(numbers);
List<Node> nodes = new ArrayList<Node>();
for (Integer data : numbers.subList(0, 5))
nodes.add(new Node(data)); // use a constructor for Node.
for (int w = 0; w < nodes.size(); w++)
System.out.println(w + ": " + nodes.get(w).data);
return nodes;
}
Your check function is wrong. Currently, it simply returns whether the last element matches num. You want to declare true (e.g. with return true;) once you find a match.
In fact, you can do everything without b. And I'm sure you can use list's contain method instead.
You should change your check method to something like:
private static boolean check(ArrayList<Node> list, int num)
{
for (Node node : list)
if (node.data == num)
return false;
return true;
}
In this way you go over the list and return false as soon as you find an equal element. If you are able to finish the loop without returning then no duplicates are found and you can return true.
This is my solution:
import java.util.ArrayList;
import java.util.Collections;
public class comboGenerator {
public static void main(String[] args) {
ArrayList<Integer> $combo = new ArrayList<Integer>(); // init. array list combo for randomization
while ($combo.size() < 6) {
int rand = (int) (Math.random()*49+1); // make new random number 1-49
if (!$combo.contains(rand)){ // check if we have that number in array list,{
$combo.add(rand); // if there is no such number then add it to array list
Collections.sort($combo); // sort the array list small >> large
}
}
System.out.println("Random combination " + $combo);
}
}
And you CAN'T get same numbers!

Categories