I have a string array and i want to retrive 15 elements at one shot without using a loop. I'm not sure whether this is possible or not
here is my code snippet using loop
String8uilder sb= new String8uilder();
for(int x=0;x<15;x++)
sb.append(array1[x]);
System.out.println(sb);
Is it possible to access all the 15 elements at once without using a loop?
Consider that array array1 already has 100 elements in it.
Thanks in advance
Are you constrained to using an array? If not, you could use other data structures that let you slice subsets of data out of them (e.g. lists).
If you must use an array, you could create a custom Iterator that iterates over a slice of the array:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class WatIterator<A> implements Iterator<A> {
private int i = 0;
private final A[] as;
private final int start;
private final int count;
public WatIterator(A[] _as, int _start, int _count) {
as = _as;
start = _start;
count = _count;
}
public synchronized boolean hasNext() {
return (i < count) && (as.length > start + i);
}
public synchronized A next() {
if (hasNext()) {
A a = as[start + i];
i = i + 1;
return a;
} else {
throw new NoSuchElementException();
}
}
public void remove() {
}
}
But to use it you're still going to have to do some kind of looping or recursion, even if you tuck it away in a toList converter:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Wat {
public static <A> List<A> toList(Iterator<A> it) {
List<A> as = new ArrayList<A>();
while (it.hasNext()) {
as.add(it.next());
}
return as;
}
public static void main(String[] args) {
String[] array = new String[100];
for (int i = 0; i < 100; i++) array[i] = Integer.toString(i);
WatIterator<String> watIterator = new WatIterator(array,0,15);
List<String> slice = toList(watIterator);
System.out.println(slice); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
}
}
Related
I am trying to find the longest possible path based on how many connections a variable number has, without repeating connections. The way I thought of doing this was creating a list that holds all points that have already been gone through, but when a path ends, and I need to check a new path, all of those old connections remain in the list. How can I restart my list from the initial point?
Putting it in the recursive function itself would just clear the list each time. Is there a better option than using a list?
Relevant code:
package testapp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.IOException;
import java.util.List;
class TestApp {
// Store list of objects we have already matched with
static List<NumberObject> holdingList = new ArrayList<NumberObject>();
//Test objects
static int[] array1 = {2,2};
static int[] array2 = {3,1};
static int[] array3 = {2,1};
static int[] array4 = {1,1};
static NumberObject eight = new NumberObject(array1, 8);
static NumberObject two = new NumberObject(array2, 2);
static NumberObject three = new NumberObject(array3, 3);
static NumberObject four = new NumberObject(array4, 4);
// Test objects ^^
public static int longestSequence(int[][] grid) {
// TODO: implement this function
// Code exists here not relevant to the problem
//Setting up a new numberList array for testing
NumberObject[] newNumberList = {eight, two, three, four};
NumberObject[] connections1 = {two, four};
NumberObject[] connections2 = {two, three};
//Adding connections
eight.connections = connections1;
four.connections = connections2;
for (NumberObject s: newNumberList){
recursive(s);
}
return 0;
}
public static void recursive(NumberObject object){
for (NumberObject x: holdingList){
System.out.println(x);
}
if (!holdingList.contains(object)){
holdingList.add(object);
if (object.hasConnections()){
NumberObject[] newobject = object.getConnections();
for(NumberObject y: newobject){
recursive(y);
}
}
else {
System.out.println(holdingList.size());
return;
}
}
else {
System.out.println(holdingList.size());
return;
}
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int numRows = 0;
int numCols = 0;
String[] firstLine = reader.readLine().split("\\s+");
numRows = Integer.parseInt(firstLine[0]);
numCols = Integer.parseInt(firstLine[1]);
int[][] grid = new int[numRows][numCols];
for (int row = 0; row < numRows; row++) {
String[] inputRow = reader.readLine().split("\\s+");
for (int col = 0; col < numCols; col++) {
grid[row][col] = Integer.parseInt(inputRow[col]);
}
}
int length = longestSequence(grid);
System.out.println(length);
}
}
class NumberObject {
int[] id;
int value;
NumberObject[] connections;
//Constructor
public NumberObject(int[] id, int value){
this.id = id;
this.value = value;
}
//print statement
public String toString(){
return ("NumberOject: Id = " + id + "\nValue = " + value);
}
//Check if it has connections
public boolean hasConnections(){
if (connections == null){
return false;
}
else if (connections.length != 0){
return true;
}
else
return false;
}
//Return the connections it has
public NumberObject[] getConnections(){
return connections;
}
}
Ideally, the image displays what I want to happen.
Instead, all the old branching connections remain on holdingList.
it should be noted paths can branch off to more than two other objects.
Instead of storing the list in a field, you could just pass an instance of a copy of your list to the function as an argument. So the signature of your function recursive would look like:
public static void recursive(NumberObject object, List<NumberObject> visited)
To hide this implementation detail, I recommend writing two functions, whereby the second function just passes an empty list to the other one.
However, I'd choose a different approach since yours acquires as many new lists as entries are in your tree. In the following implementation, you only have one list per "tree end". Moreover, just like in the previous suggestion, this keeps your class stateless.
static List<NumberObject> findLongestPath(NumberObject currentNode) {
if (currentNode.getConnectedNodes().isEmpty()) {
List<NumberObject> result = new ArrayList<>();
result.add(currentNode);
return result;
}
List<NumberObject> longestPath = currentNode.getConnectedNodes().stream()
.map(PathFinder::findLongestPath)
.max(Comparator.comparing(List::size))
.get();
longestPath.add(currentNode);
return longestPath;
}
I need to find all combinations from size n that consists of the numbers in numbers array. I tried to do it with the function I wrote below but it takes a lot of time and memory to do it like that.
Is there a way to do it more efficient?
void createCombinationArray(ArrayList<Integer> numbers, int n, ArrayList<Integer> start) {
if (start.size() >= n) {
monthsComb.add(new ArrayList<>(start));
} else {
for (Integer x : numbers) {
start.add(x);
createCombinationArray(numbers, n, start);
start.remove(start.lastIndexOf(x));
}
}
}
One way to do it more efficently (both for time and memory) is to store the result as int[][] instead of Collection<List<Integer>> (which I assume to be the type of the monthsComb field). You can do this because you know that if you have k numbers the result will be Binomial(n, k) combinations of n numbers.
Another way (as #Phia-CM suggested) would be to implement a non-recoursive version of the algorithm.
I know they are both uneasy to implement, but that's the way for efficiency.
Ask yourself whether you really need to generate all of these lists ahead of time. Maybe it would be acceptable to generate them on demand.
Keep in mind that each of these lists can be represented by a number with numbers.length bits, n or more of which are set. You could work with a data structure of this sort to reference a list external to it.
It would be quite straightforward to write a List implementation with this behavior.
import java.util.BitSet;
import java.util.List;
public class SelectiveList<T> implements List<T> {
private final BitSet bitSet;
private final List<T> list;
public SelectiveList(BitSet bitSet, List<T> list) {
this.bitSet = bitSet;
this.list = list;
}
#Override
public T get(int index) {
return list.get(nthOnBit(index));
}
private int nthOnBit(int n) {
int onBits = 0;
int i;
for (i = bitSet.nextSetBit(0); i >= 0 && onBits < n; i = bitSet.nextSetBit(i + 1)) {
onBits++;
}
if (onBits < n) {
throw new IllegalArgumentException();
}
return i;
}
// etc.
}
You may try this:
package combination;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Combination implements Iterator<List<Integer>> {
public Combination(final List<Integer> numbers, final int n) {
this.numbers = numbers;
this.n = n;
this.current = BigInteger.valueOf(0);
this.radix = BigInteger.valueOf(numbers.size());
this.size = this.radix.pow(n);
}
#Override
public final boolean hasNext() {
return this.current.compareTo(size) < 0;
}
#Override
public final List<Integer> next() {
List<Integer> result = new ArrayList(this.n);
BigInteger value = this.current;
for(int i=0; i<n; i++) {
result.add(i, this.numbers.get(
value.mod(this.radix).intValueExact()));
value = value.divide(this.radix);
}
this.current = this.current.add(BigInteger.valueOf(1));
return result;
}
private final List<Integer> numbers;
private final int n;
private BigInteger current;
private final BigInteger size;
private final BigInteger radix;
public static void main(String[] args) {
Combination cb = new Combination(Arrays.asList(0, 2, 4, 6), 3);
while (cb.hasNext()) {
System.out.println(cb.next());
}
}
}
Okay I am a pretty beginner java coder, and I am doing an assignment where I am stuck. I need to create a generic method (sort) that sorts a Type array according to frequency, basically, I am taking the CountingSort Algorithm and making it a generic method. This is where I am lost. I can't seem to figure out how to do this.
Here is a link to my instructions,
https://classes.cs.siue.edu/pluginfile.php/7068/mod_assign/intro/150mp08.pdf
Code:
Driver Class
package mp08;
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Lists array = new Lists();
array.populateLists();
System.out.println("Original Int List: \n");
array.sort(Lists.intList);
System.out.println("Sorted Int List: \n");
}
}
Lists Class
package mp08;
import java.util.Arrays;
import java.util.Random;
public class Lists {
public static Integer[] intList;
public static Integer[] sortedintList;
public static Integer[] frequency;
public static Character[] charList;
public static Character[] sortedcharList;
public static int MAX_SIZE = 101;
public static int lengthInt;
public static int lengthChar;
public Lists(){
this.intList = new Integer[MAX_SIZE];
this.sortedintList = new Integer[MAX_SIZE];
this.charList = new Character[MAX_SIZE];
this.sortedcharList = new Character[MAX_SIZE];
this.frequency = new Integer[MAX_SIZE];
this.lengthInt = 0;
this.lengthChar = 0;
}
//Makes random integer for populated lists method.
public int randomInt(int min, int max){
Random rand = new Random();
int randomNum = rand.nextInt((max-min)+1)+min;
return randomNum;
}
//Makes random character for populated lists method.
public char randomChar(){
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int N = alphabet.length();
Random rand = new Random();
char randomLet = alphabet.charAt(rand.nextInt(N));
return randomLet;
}
//Populates intList and charList with random values.
public void populateLists(){
for (int i = 0; i < MAX_SIZE; i++) {
intList[i] = randomInt(1,100);
lengthInt++;
}
for (int i = 0; i < MAX_SIZE; i++) {
charList[i] = randomChar();
lengthChar++;
}
}
//Returns sorted array
public Integer[] sorted(){
return intList;
}
public static <T> void sort(T[] array) {
// array to be sorted in, this array is necessary
// when we sort object datatypes, if we don't,
// we can sort directly into the input array
Integer[] aux = new Integer[array.length];
// find the smallest and the largest value
int min = 1;
int max = 101;
// init array of frequencies
int[] counts = new int[max - min + 1];
// init the frequencies
for (int i = 0; i < array.length; i++) {
counts[array[i] - min]++;
}
// recalculate the array - create the array of occurence
counts[0]--;
for (int i = 1; i < counts.length; i++) {
counts[i] = counts[i] + counts[i-1];
}
/*
Sort the array right to the left
1) Look up in the array of occurences the last occurence of the given value
2) Place it into the sorted array
3) Decrement the index of the last occurence of the given value
4) Continue with the previous value of the input array (goto set1),
terminate if all values were already sorted
*/
for (int i = array.length - 1; i >= 0; i--) {
aux[counts[array[i] - min]--] = array[i];
}
}
public static void main(String[] args) {
Integer [] unsorted = {5,3,0,2,4,1,0,5,2,3,1,4};
System.out.println("Before: " + Arrays.toString(unsorted));
Integer [] sorted = sort(unsorted);
System.out.println("After: " + Arrays.toString(sorted));
}
}
I obviously have not finished my driver class yet and I would appreciate any help I can get!
There's no generic way for any Comparable type to get its ordinal number. Sometimes such numbers do not exist at all (for example, String is Comparable, but you cannot map any String to the integer number). I can propose two solutions.
First one is to store counts not in the array, but in TreeMap instead creating new entries on demand (using Java-8 syntax for brevity):
public static <T extends Comparable<T>> void sort(T[] array) {
Map<T, Integer> counts = new TreeMap<>();
for(T t : array) {
counts.merge(t, 1, Integer::sum);
}
int i=0;
for(Map.Entry<T, Integer> entry : counts.entrySet()) {
for(int j=0; j<entry.getValue(); j++)
array[i++] = entry.getKey();
}
}
public static void main(String[] args) {
Integer[] data = { 5, 3, 0, 2, 4, 1, 0, 5, 2, 3, 1, 4 };
System.out.println("Before: " + Arrays.toString(data));
sort(data);
System.out.println("After: " + Arrays.toString(data));
Character[] chars = { 'A', 'Z', 'B', 'D', 'F' };
System.out.println("Before: " + Arrays.toString(chars));
sort(chars);
System.out.println("After: " + Arrays.toString(chars));
}
Such solution looks clean, but probably not very optimal (though its advantage is that it does not care whether all numbers are from 1 to 100 or not).
Another possible solution is to create some additional interface which defines ordering for given type:
public interface Ordering<T> {
int toOrdinal(T obj);
T toObject(int ordinal);
}
public class IntegerOrdering implements Ordering<Integer> {
#Override
public int toOrdinal(Integer obj) {
return obj;
}
#Override
public Integer toObject(int ordinal) {
return ordinal;
}
}
public class CharacterOrdering implements Ordering<Character> {
#Override
public int toOrdinal(Character obj) {
return obj;
}
#Override
public Character toObject(int ordinal) {
return (char)ordinal;
}
}
Now you may make your sort method accepting the ordering parameter:
public static <T> void sort(T[] array, Ordering<T> ordering) { ... }
Every time you need to get counts array index by T object, just call ordering.toOrdinal(object). Every time you need to get object by array index, just use ordering.toObject(index). So, for example, instead of
counts[array[i] - min]++;
Use
counts[ordering.toOrdinal(array[i]) - min]++;
And call the sorting method like this:
sort(characterArray, new CharacterOrdering());
sort(integerArray, new IntegerOrdering());
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Here is my example - pick random number from 1-20, then from 2-21, 3-22 and so on, while
excluding previous picks. I am new to Java, and doing something wrong.
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
public class RandomGenerator {
static int temp;
public static void main(String[] args) {
List<Integer> randomNumberArray = new ArrayList<Integer>();
Random RandomNumber = new Random();
for (int i = 0; i<=20; i++)
{
temp = RandomNumber.nextInt(i+20) +1+i;
if (!randomNumberArray.contains(temp))
{
{
randomNumberArray.add(temp);
}
}
System.out.println(randomNumberArray);
}
There are a couple of things to go over.
1) If your number sees that there is a duplicate then it will skip it and continue with the next number, for example if you run it 5 times and it finds a duplicate once, then the resulting list of numbers will have only 4 numbers not 5! since it skipped one. (Not sure if this is what you wanted or not)
2) Your randomly generated number doesn't grow the way you expect it to grow.
For example: At the sixth iteration over the loop your random number will generate as:
RandomNumber.nextInt(25) +6;
That means that the number range there isn't 6-26 but 6-30!
Because: nextInt will return an int between 0 and 24 and then that int is added another 6 to it.
EDIT :
To tackle your first problem you can continue to generate numbers until you generate one that is not a duplicate for that single cycle of the for loop.
For this you can utilize the do-while loop so that it executes the number generation at least once before checking whether the number is a duplicate within the for loop.
So you can adjust your for loop from:
for (int i = 0; i<=20; i++)
{
temp = RandomNumber.nextInt(20) +1+i;
if (!randomNumberArray.contains(temp))
{
{
randomNumberArray.add(temp);
}
}
System.out.println(randomNumberArray);
}
into:
for (int i = 0; i<=20; i++)
{
do {
temp = RandomNumber.nextInt(20) +1+i;
} while (randomNumberArray.contains(temp));
randomNumberArray.add(temp);
System.out.println(randomNumberArray);
}
Notice that the check in the while expression is the opposite (does not have the exclamation mark) of what was in the if expression in the for loop before, since we do want to continue generating new random numbers while our numbers are duplicates.
And since we are still looping within that one cycle of the for loop, it will always generate the number with the appropriate value of i which was set for that for cycle.
You aren't excluding previous picks. Something like this will print twenty random numbers (e.g. all random numbers from 1-20).
public static void main(String[] args) {
java.util.Set<Integer> picked = new TreeSet<Integer>();
Random rand = new Random();
while (picked.size() < 20) {
int temp = 1+rand.nextInt(20);
if (picked.contains(temp)) {
continue;
}
picked.add(temp);
System.out.println(temp);
}
}
I'm not sure I understand your "stepping" idea, but add this for temp and it will do that too -
int temp = 1+picked.size()+rand.nextInt(20+picked.size());
Since the range of allowed elements isn't too big, you can also hold the pool of all possible numbers and pick one of them. You can use e.g. RandomSet from this answer.
import java.util.*;
import java.lang.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
static class RandomSet<E> extends AbstractSet<E> {
List<E> dta = new ArrayList<E>();
Map<E, Integer> idx = new HashMap<E, Integer>();
public RandomSet() {
}
public RandomSet(Collection<E> items) {
for (E item : items) {
idx.put(item, dta.size());
dta.add(item);
}
}
#Override
public boolean add(E item) {
if (idx.containsKey(item)) {
return false;
}
idx.put(item, dta.size());
dta.add(item);
return true;
}
/**
* Override element at position <code>id</code> with last element.
* #param id
*/
public E removeAt(int id) {
if (id >= dta.size()) {
return null;
}
E res = dta.get(id);
idx.remove(res);
E last = dta.remove(dta.size() - 1);
// skip filling the hole if last is removed
if (id < dta.size()) {
idx.put(last, id);
dta.set(id, last);
}
return res;
}
#Override
public boolean remove(Object item) {
#SuppressWarnings(value = "element-type-mismatch")
Integer id = idx.get(item);
if (id == null) {
return false;
}
removeAt(id);
return true;
}
public E get(int i) {
return dta.get(i);
}
public E pollRandom(Random rnd) {
if (dta.isEmpty()) {
return null;
}
int id = rnd.nextInt(dta.size());
return removeAt(id);
}
#Override
public int size() {
return dta.size();
}
#Override
public Iterator<E> iterator() {
return dta.iterator();
}
}
public static void main (String[] args) throws java.lang.Exception
{
RandomSet<Integer> rs = new RandomSet<Integer>();
for (int i = 0; i < 20; ++i) {
rs.add(i);
}
int count = 50;
Random r = new Random();
for (int i = 0; i < count; i++) {
System.out.println(rs.pollRandom(r));
rs.remove(i);
rs.add(i + 20);
}
}
}
Using the smart structure the overall time complexity is O(N + K), where N is the number of requested polls and K is the size of the pool.
Running Ideone example : http://ideone.com/Sfltr7
The trick here is to use Collections.shuffle(List list):
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
Collections.shuffle(list);
System.out.println(list);
The progressive version goes something like this:
// Wrap it in an ArrayList so I can modify it.
List<Integer> list = new ArrayList(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20));
for (int i = 21; i < 25; i++) {
System.out.println(list);
// Shuffle it.
Collections.shuffle(list);
// Grab one.
Integer take = list.get(0);
list.remove(take);
System.out.println("Took " + take);
// Add my new candidate.
list.add(i);
}
Or you could go the whole hog and make it an Iterable:
public static class CreepingRandom implements Iterable<Integer> {
// The starting list.
private final List<Integer> start;
// How many steps to add.
private final int steps;
// What int to start adding.
private final int from;
public CreepingRandom(int initialSize, int from, int steps) {
// Make my start list.
start = new ArrayList<Integer>(initialSize);
// Fill it.
for (int i = 1; i <= initialSize; i++) {
start.add(i);
}
// Remember where to start from.
this.from = from;
// Remember how many steps.
this.steps = steps;
}
#Override
public Iterator<Integer> iterator() {
return new CreepingIterator();
}
private class CreepingIterator implements Iterator<Integer> {
// Track how many I've delivered.
int delivered = 0;
// The next number to add.
int add = from;
// My current list.
final ArrayList<Integer> list = new ArrayList(start);
#Override
public boolean hasNext() {
return delivered < steps;
}
#Override
public Integer next() {
// Shuffle it.
Collections.shuffle(list);
// Pull one out.
Integer next = list.get(0);
// Add my new one in.
list.set(0, add++);
// Count them.
delivered += 1;
return next;
}
}
}
public void test() {
for (Integer i : new CreepingRandom(20, 21, 100)) {
System.out.println(i);
}
}
private class CreepingIterator implements Iterator<Integer> {
// Track how many I've delivered.
int delivered = 0;
// The next number to add.
int add = from;
// My current list.
final ArrayList<Integer> list;
CreepingIterator() {
// Copy the start list - Use LinkedList for efficiency of add and removeFirst.
list = new ArrayList(start);
}
#Override
public boolean hasNext() {
return delivered < steps;
}
#Override
public Integer next() {
// Shuffle it.
Collections.shuffle(list);
// Pull one out.
Integer next = list.get(0);
// Add my new one in.
list.set(0, add++);
// Count them.
delivered += 1;
return next;
}
}
}
public void test() {
for (Integer i : new CreepingRandom(20, 21, 100)) {
System.out.println(i);
}
}
I'm doing some exercises on generic programming; is there a way to take a class that implements List and return a reversed version of that same class? It seems this should be feasible as this, at least taking the term at face value, is "generic programming" writ large.
Maybe by performing an in-place reversal? I also considered Collections.reverse(), but it's a void method.
Here is my attempt and demo:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;
public class ReverseDemo {
public static <T> List<T> reverse(List<T> list) {
List<T> reversed = new ArrayList<T>();
for (int i = list.size() - 1; i >= 0; i--) {
reversed.add(list.get(i));
}
return reversed;
}
public static void main(String[] args) {
LinkedList<Integer> linkedInt = new LinkedList<Integer>();
ArrayList<Double> arrayDouble = new ArrayList<Double>();
for (int k = 0; k < 10; k++) {
double doubleNum = 10*Math.random();
int intNum = (int) (10*Math.random());
linkedInt.add(intNum);
arrayDouble.add(doubleNum);
}
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse(linkedInt).toArray()));
System.out.println(reverse(linkedInt) instanceof LinkedList<?>); // false
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse(arrayDouble).toArray()));
System.out.println(reverse(arrayDouble) instanceof ArrayList<?>); // true
}
}
Incidentally this is my first post here, does anyone know the best way to post code directly from Eclipse while preserving the spacing and indentation therefrom? I've used the four-spaces method specified here, but it's a bit inconsistent.
The Guava library has a nice, non-destructive solution to the problem. See Lists.reverse(List).
They define a suite of ReverseList classes that wrap the input List. From there, it's just a matter of translating all of calls (although "just" might be understating things a bit).
If you want to preserve the original list, you can try using:
originalList.getClass().newInstance()
That is not a 100% correct solution as it may throw if the original class does not have a default constructor. However, most collections have default constructors that create empty instances.
try following
public static <T> List<T> reverse(List<T> list) {
List<T> reversed=null;
try {
reversed = list.getClass().newInstance();
Collections.reverse(list);
reversed.addAll(list);
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
return reversed;
}
All java.util implementations of List are cloneable, so you could use that, but sadly not without resorting to reflection. While on the reflection chapter, you may also use the copy-constructor, which is also sported by all Java's collections.
There is no fully general approach to non-destructive reversing, unfortunately.
Destructive reversing, on the other hand, is too trivial to be interesting.
The Collections.reverse() might be void, but that's only because you should be passing in the List to be reversed.
List<T> myList = ...;
Collections.reverse(myList);
You now have a reversed list.
This seems to work:
import java.util.*;
public class ReverseListDemo
{
public static void main(String[] args)
{
List<String> original = Arrays.asList("A", "B", "C");
List<String> reversal = reverse(original);
System.out.println("Original: " + original);
System.out.println("Reversal: " + reversal);
}
public static <T> List<T> reverse(List<T> list)
{
T[] objects = (T[]) list.toArray();
List<T> copy = Arrays.asList(objects);
Collections.reverse(copy);
return copy;
}
}
Thanks for the replies everyone. I wrote a method reverse2 which works at least for implementing classes ArrayList and LinkedList. Not sure how efficient it is.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Arrays;
// See http://stackoverflow.com/questions/16799066/return-reversed-generic-list-type-in-java.
public class ReverseDemo {
public static <T> List<T> reverse1(List<T> list) {
List<T> reversed = new ArrayList<T>();
for (int i = list.size() - 1; i > -1; i--) {
reversed.add(list.get(i));
}
return reversed;
}
public static <T> List<T> reverse2(List<T> list) {
int size = list.size();
ArrayList<T> obArray = new ArrayList<T>();
obArray.addAll(list);
ListIterator<T> iter = list.listIterator();
for (int i = 0; i < size; i++) {
iter.next();
iter.set(obArray.get(size - 1 - i));
}
return list;
}
public static void main(String[] args) {
LinkedList<Integer> linkedInt = new LinkedList<Integer>();
ArrayList<Double> arrayDouble = new ArrayList<Double>();
for (int k = 0; k < 10; k++) {
double doubleNum = 10*Math.random();
int intNum = (int) (10*Math.random());
linkedInt.add(intNum);
arrayDouble.add(doubleNum);
}
TextIO.putln("Testing reverse1.");
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse1(linkedInt).toArray()));
TextIO.putln("LinkedList structure preserved?");
System.out.println(reverse1(linkedInt) instanceof LinkedList<?>);
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse1(arrayDouble).toArray()));
TextIO.putln("ArrayList structure preserved?");
System.out.println(reverse1(arrayDouble) instanceof ArrayList<?>);
TextIO.putln("\nTesting reverse2.");
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse2(linkedInt).toArray()));
TextIO.putln("LinkedList structure preserved?");
System.out.println(reverse2(linkedInt) instanceof LinkedList<?>);
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse2(arrayDouble).toArray()));
TextIO.putln("ArrayList structure preserved?");
System.out.println(reverse2(arrayDouble) instanceof ArrayList<?>);
}
}
console output:
Testing reverse1.
[8, 0, 1, 9, 3, 4, 3, 7, 6, 3]
[3, 6, 7, 3, 4, 3, 9, 1, 0, 8]
LinkedList structure preserved?
false
[8.301783107294664, 5.434068303620735, 9.095396759542615, 0.41823972682620836, 9.56659902304762, 3.2560723280079085, 4.037362000077436, 9.731919590391389, 0.5243645318825874, 5.9432185528462975]
[5.9432185528462975, 0.5243645318825874, 9.731919590391389, 4.037362000077436, 3.2560723280079085, 9.56659902304762, 0.41823972682620836, 9.095396759542615, 5.434068303620735, 8.301783107294664]
ArrayList structure preserved?
true
Testing reverse2.
[8, 0, 1, 9, 3, 4, 3, 7, 6, 3]
[3, 6, 7, 3, 4, 3, 9, 1, 0, 8]
LinkedList structure preserved?
true
[8.301783107294664, 5.434068303620735, 9.095396759542615, 0.41823972682620836, 9.56659902304762, 3.2560723280079085, 4.037362000077436, 9.731919590391389, 0.5243645318825874, 5.9432185528462975]
[5.9432185528462975, 0.5243645318825874, 9.731919590391389, 4.037362000077436, 3.2560723280079085, 9.56659902304762, 0.41823972682620836, 9.095396759542615, 5.434068303620735, 8.301783107294664]
ArrayList structure preserved?
true