Access directly a column inside an ArrayList in Java - java

I am trying to access not a single element inside a 2D ArrayList but an entire column. Since it is very easy to do that when you need a row (since the 2D Array is read by row and columns), it was not so trivial to me to do the same for a column.
Do you have any suggestion relevant to that?
Any kind of help will be very appreciated!
Many thanks!

There is no way to directly access a column in a 2-D row-oriented list. You can, however, always extract the required value.
To retrieve, column at index n, you can simply run:
twoDList.stream().map(innerList -> innerList.get(n))
.collect(Collectors.toList());
This can also be easily changed to a normal for-each loop.
List<T> column = new ArrayList<T>();
for(List<T> row: twoDList) {
column.add(row.get(n));
}

I posted something similar here recently.
Here I create a ColumnList object that allows me to manipulate a single column of a 2D array. In this case I am sorting it.
class ColumnList<T> extends AbstractList<T> implements List<T> {
private final T[][] array;
private final int column;
public ColumnList(T[][] array, int column) {
this.array = array;
this.column = column;
}
#Override
public T get(int index) {
return array[index][column];
}
#Override
public T set(int index, T element) {
return array[index][column] = element;
}
#Override
public int size() {
return array.length;
}
}
public void test(String[] args) {
Integer[][] array = {
{6, 8, 9, 16},
{0, 6, -3, 4},
{18, 2, 1, 11}
};
System.out.println("Before: " + Arrays.deepToString(array));
// Sort each column separately.
for (int i = 0; i < array[0].length; i++) {
List<Integer> column = new ColumnList<>(array, i);
Collections.sort(column);
}
System.out.println("After: " + Arrays.deepToString(array));
}

The best way is to use a List within a List:
List<List<String>> listWithList = new ArrayList<List<String>>();
To get the child List from the parent List you need to call for example 0 for the first child List:
List<String> anotherList = new ArrayList<String>();
anotherList = listWithList.get(0); // get the first complete List
To get a String from the child List you need to call:
String someText = anotherList.get(0); // get the first String
or directly from the List within the List:
String moreText = listWithList.get(0).get(0); // get the first String from the first List

Related

Creating an Array List from scratch

I was wondering if anyone would be able to point me in the correct direction in regards to creating my own array list methods. For instance, the current project I am assigned to does not allow for me to use the methods given to me for free like in the following example.
package com.tutorialspoint;
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
// create an empty array list with an initial capacity
ArrayList<Integer> arrlist = new ArrayList<Integer>(5);
// use add() method to add elements in the list
arrlist.add(15);
arrlist.add(22);
arrlist.add(30);
arrlist.add(40);
// adding element 25 at third position
arrlist.add(2,25);
// let us print all the elements available in list
for (Integer number : arrlist) {
System.out.println("Number = " + number);
}
}
}
This example shows the add() method. For my project I have to create this method myself and call it from a different file within my package.
I find this as an interesting problem. I am always curious about how things work at the raw level.
If you think about it, an ArrayList is basically just an array that you can expand. So you can either have a really big array (which would take a lot of memory for one ArrayList) or every time you add something, you make a new bigger array and copy the contents and add the new item (which I think the performance is O(N)).
This is my attempt without using any libraries:
public class MyArrayList<T>
{
private T[] asArray;
#SuppressWarnings("unchecked")
public MyArrayList()
{
asArray = (T[]) new Object[0];
}
public void add(T t)
{
#SuppressWarnings("unchecked")
T[] temp = (T[]) new Object[asArray.length + 1];
// copy everything over to the new array
for (int i = 0; i < asArray.length; i++)
{
temp[i] = asArray[i];
}
// add the new element
temp[asArray.length] = t;
asArray = temp;
}
public void remove(int index)
{
if (index < 0 || index >= asArray.length) return;
#SuppressWarnings("unchecked")
T[] temp = (T[]) new Object[asArray.length - 1];
boolean found = false;
// copy everything over to the new element
for (int i = 0; i < asArray.length; i++)
{
// don't copy if the indices are the same
if (i == index)
{
found = true;
continue;
}
temp[i - (found ? 1 : 0)] = asArray[i]; // it's i - 1 after the removed object so then it doesn't leave a gap and it doesn't go over the array's length
}
asArray = temp;
}
public T get(int index)
{
return asArray[index];
}
}
I am quite proud of this code. :) I consider Short_Teeth's code cheating because the class is a subclass and, well, doesn't add anything. I hope I helped.
This is very easy to understand; However, I explained a little bit in comments.
public class MyArrayList<E extends Object> {
private static int initialCapacity = 5;
private static int currentSize;
private Object[] myArrayList = {}, temp = {};
private static int currentIndex = 0;
public static void main(String[] args) {
MyArrayList arrList = new MyArrayList();
arrList.add("123"); //add String
arrList.printAllElements();
arrList.add(new Integer(111)); //add Integer
arrList.printAllElements();
arrList.add(new Float("34.56")); //add Integer
arrList.printAllElements();
arrList.delete("123");
arrList.printAllElements();
arrList.delete(123);
arrList.printAllElements();
arrList.delete(123);
arrList.printAllElements();
}
public MyArrayList() { //creates default sized Array of Objects
myArrayList = new Object[initialCapacity]; //generic expression
/* everytime I cross my capacity,
I make double size of Object Array, copy all the elements from past myObject Array Object
*/
}
public MyArrayList(int size) { //creates custom sized Array of Objects
myArrayList = new Object[size];
}
public void add(Object anyObj) {
//add element directy
myArrayList[currentIndex] = anyObj;
currentSize = myArrayList.length;
currentIndex++;
if (currentIndex == currentSize) {
createDoubleSizedObjectArray(currentSize);
}
}
//print all elements
public void printAllElements() {
System.out.println("Displaying list : ");
for (int i = 0; i < currentIndex; i++) {
System.out.println(myArrayList[i].toString());
}
}
private void createDoubleSizedObjectArray(int currentSize) {
temp = myArrayList.clone();
myArrayList = new MyArrayList[2 * currentSize]; //myObject pointer big size data structure
// myObject = temp.clone(); //probably I can do this here as well. Need to check this
System.arraycopy(temp, 0, myArrayList, 0, currentSize);
}
void delete(Object object) {
//if already empty
if (currentIndex == 0) {
System.out.println("Already empty!");
return;
}
//you don't need to delete anything. I can simply override the storage
currentIndex--;
}
}
import java.util.ArrayList;
public class MyArrayList<E> extends ArrayList<E>{
private static final long serialVersionUID = -5164702379587769464L;
public void newMethod(){
// No implementation
}
}
This is a class which extends from ArrayList and a method called newMethod() was added to this class.
Below we are calling this newly created method in your case you must implement the add to this newly created method.
public class Hello {
public static void main(String args[]) {
MyArrayList<Integer> myList = new MyArrayList<Integer>();
// It has the ArrayList add() method as this new class extends from ArrayList (all the ArrayList methods are included)
myList.add(2);
// The newly created method in your case you need to implement the add yourself
myList.newMethod();
}
}
This could also be a good link for what you need.
http://www.java2novice.com/java-interview-programs/arraylist-implementation/
I also recomend that you try to implement and solve your problems first and then ask questions about a specific problem, and only after you done a good research about what may be causing this problem (There are lots of resources out there). If you done some research before you asked this question, I'm pretty sure that you would have been able to solve everything on your own.
Hope you find this information useful. Good luck.

Java Lambda: Iterate over 2 dim-array keeping the current index

I'm new to Java 8's Lambda Expressions and I want to formulate the following:
I have a 2-dimensional array which I want to iterate over several times in my application code and do stuff with the items in the array. Before i'd do the following:
public static abstract class BlaBlaIterator {
private final BlaBla[][] blabla;
public BlaBlaIterator(final BlaBla[][] blabla) {
this.blabla = blabla;
}
public void iterate() {
final int size = blabla.length;
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
final BlaBla bla = blabla[x][y];
iterateAction(x, y, bla, bla == null);
}
}
}
public abstract void iterateAction(int x, int y, BlaBla bla, boolean isNull);
}
and then
BlaBla[][] blabla = ...
new BlaBlaIterator(blabla) {
#Override
public void iterateAction(final int x, final int y, final BlaBla bla, final boolean isNull) {
//...
}
}.iterate();
Crucial thing: I need access to the current x/y and I need to get calculated things like the isNull.
What I want to do now is to convert this to lambda. I want to write something like this:
BlaBla[] blabla = ...
blabla.stream().forEach((x, y, blabla, isNull) -> ... );
To get a stream from the 2-dimensional Array I can do
Arrays.stream(field).flatMap(x -> Arrays.stream(x))
But then I loose the x/y info and cannot pass calculated stuff like isNull. How can i do this?
To be honest I would keep the traditionnal nested loop, IMO this is a much cleaner approach. Streams are not a substition for all the "old" Java code. Nevertheless, I posted some possible approaches.
First approach
Here's a first possible approach (Object-oriented). Create a class ArrayElement to hold the indices:
class ArrayElement<V> {
public final int row;
public final int col;
public final V elem;
...
}
Then you'll need to create a method that creates a Stream of elements from a single array (the one that we will call for flatMap), and iterateAction just print out the current instance
private static <T> Stream<ArrayElement<T>> createStream(int row, T[] arr) {
OfInt columns = IntStream.range(0, arr.length).iterator();
return Arrays.stream(arr).map(elem -> new ArrayElement<>(row, columns.nextInt(), elem));
}
private static <V> void iterateAction(ArrayElement<V> elem) {
System.out.println(elem);
}
Finally the main looks like this:
String[][] arr = {{"One", "Two"}, {"Three", "Four"}};
OfInt rows = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr)
.flatMap(subArr -> createStream(rows.nextInt(), subArr))
.forEach(Main::iterateAction);
and outputs:
ArrayElement [row=0, col=0, elem=One]
ArrayElement [row=0, col=1, elem=Two]
ArrayElement [row=1, col=0, elem=Three]
ArrayElement [row=1, col=1, elem=Four]
This solution has the disadvantage that it creates a new Object for each Object in the array.
Second approach
The second approach is more direct, it's the same idea but you don't create a new ArrayElement instance for each elem in the array. Again this could be done in a one liner but the lamdba would become ugly so I splitted those up in methods (like in the first approach):
public class Main {
public static void main(String[] args) {
String[][] arr = { {"One", "Two"}, {null, "Four"}};
OfInt rows = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr).forEach(subArr -> iterate(subArr, rows.nextInt()));
}
static <T> void iterate(T[] arr, int row) {
OfInt columns = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr).forEach(elem -> iterateAction(row, columns.nextInt(), elem, elem == null));
}
static <T> void iterateAction(int x, int y, T elem, boolean isNull) {
System.out.println(x+", "+y+", "+elem+", "+isNull);
}
}
and it outputs:
0, 0, One, false
0, 1, Two, false
1, 0, null, true
1, 1, Four, false
Third approach
Using two instances of AtomicInteger
String[][] arr = {{"One", "Two"}, {null, "Four"}};
AtomicInteger rows = new AtomicInteger();
Arrays.stream(arr).forEach(subArr -> {
int row = rows.getAndIncrement();
AtomicInteger colums = new AtomicInteger();
Arrays.stream(subArr).forEach(e -> iterateAction(row, colums.getAndIncrement(), e, e == null));
});
which produces the same output as above.
My conclusion
It's duable using Streams but I really prefer the nested loop in your use-case since you need both the x and y values.
This is an issue, similar to the different forms of for-loop. If you are not interested in the indices, you can imply say:
for(BlaBla[] array: blabla) for(BlaBla element: array) action(element);
But if you are interested in the indices, you can’t use the for-each loop but have to iterate over the indices and get the array element in the loop body. Similarly, you have to stream the indices when using Stream and need the indices:
IntStream.range(0, blabla.length)
.forEach(x -> IntStream.range(0, blabla[x].length)
.forEach(y -> {
final BlaBla bla = blabla[x][y];
iterateAction(x, y, bla, bla == null);
})
);
This is a 1:1 translation which has the advantage of not requiring additional classes, but it consists of two distinct Stream operations rather than one fused operation, as would be preferred.
A single, fused operation might look like this:
helped class:
class ArrayElement {
final int x, y;
BlaBla element;
final boolean isNull;
ArrayElement(int x, int y, BlaBla obj) {
this.x=x; this.y=y;
element=obj; isNull=obj==null;
}
}
actual operation:
IntStream.range(0, blabla.length).boxed()
.flatMap(x -> IntStream.range(0, blabla[x].length)
.mapToObj(y->new ArrayElement(x, y, blabla[x][y])))
.forEach(e -> iterateAction(e.x, e.y, e.element, e.isNull));

Getting unique elements of List

all I have list containing Duplicate values I want somehow to get only Unique values from it and store it another list or set.So that I can perform some operation on it.
My code:
{
List<Integer[]> list1 = new ArrayList<Integer[]>();
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 2,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 3,10 });
for(int i=0;i<list1.size();i++)
{
System.out.println("I - 0 :"+list1.get(i)[0]+"\t I - 1 :"+list1.get(i)[1]+"\n");
}
Set<Integer[]> uniquelist = new HashSet<Integer[]>(list1);
for(Integer[] number: uniquelist){
System.out.println(number[0]+"\t"+number[1]);
}
}
I want the result {1,10;2,10;3,10} to be in separate list.When i googled I got to know for unique we should use set as in Set<Integer[]> uniquelist = new HashSet<Integer[]>(list1); But after doing this I dont know how to access each elements Thanks in advance
Output:
1 10
2 10
1 10
3 10
1 10
1 10
You won't get the result you want using the normal Set approach. As your List contains Integer[], and then won't be considered unique by default. All the array objects are distinct. So, your Set will contain the same elements as your list. However, you can define your Custom Comparator, and use it with a TreeSet constructor.
Another way of doing it can be, define a method contains(List<Integer[]> list, Integer[] value), which checks whether your list contains that array. Define a list named uniqueList. Now, iterate over your original list, and then for each value, call contains method passing uniqueList and that value, as parameters.
Here's how your contains method would look like: -
public static boolean contains(List<Integer[]> list, Integer[] value) {
for (Integer[] arr: list) {
// We can compare two arrays using `Arrays.equals` method.
if (Arrays.equals(arr, value)) {
return true;
}
}
return false;
}
So, you can see that, checking for containment is not the same as, how it would look for just Integer.
Now, from your main method, use this code: -
List<Integer[]> unique = new ArrayList<Integer[]>();
for (Integer[] arr: list1) {
// Use your method here, to test whether this value - `arr`
// is already in `unique` List or not. If not, then add it.
if (!contains(unique, arr)) {
unique.add(arr);
}
}
for (Integer[] arr: unique) {
System.out.println(arr);
}
I would rather use a Set implementation in this case. Use LinkedHashSet if you want your elements to be ordered.
You could declare a class IntegerPair to hold your pairs:
class IntegerPair {
private int key;
private int value;
public IntegerPair(int k, int v) {
key = k;
value = v;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public int hashCode() {
return key * value;
}
public boolean equals(Object o) {
if (!(o instanceof IntegerPair)) {
return false;
}
IntegerPair other = (IntegerPair) o;
return key == other.key && value == other.value;
}
}
Declare it this way:
Set<IntegerPair> set = new LinkedHashSet<IntegerPair>();
Instead of putting new Integer[] values, just do set.add(new IntegerPair(1, 10));
You can loop through your elements using the foreach approach:
for (IntegerPair value : set) {
System.out.println(value.getKey() + " = " + value.getValue());
}
You can access elements by Iterator or by using for each loop
for(Integer number: setOfNumbers){
System.out.println(number);
}
Put them into set using your custom comparator like following:
new TreeSet(list1, new Comparator<Integer[]>() {
public int compare(Integer[] one, Integer[] two) {
int n = one.length;
for (int i = 0; i < n; i++) {
int comp = one.compareTo(two);
if (comp != 0) {
return comp;
}
}
return 0;
}
});
Pay attention that I used TreeSet that can accept custom comparator. It is because you are dealing with arrays. If however you define your own class that holds 2 int values you can make it to implement equals() and hashCode() that allows using any Set implementation.
the Integer[] number in your for loop is an array. to get the values inside you have to use number[index] instruction. to do that you can either do a classic while or for loop using a variable as an index
for(int i=0;i<number.length;i++) {
...
}
or a foreach loop:
for(Integer num : number){
...
}
This may help you...
public static void main(String [] args){
Set<Integer []> set = new TreeSet<Integer []>(new Comparator<Integer[]>(){
public int compare(Integer[] o1, Integer[] o2) {
if(o1.length == o2.length){
for(int i = 0; i < o1.length; i++){
if(o1[i] != o2[i]){
return -1;
}
}
return 0;
}
return -1;
}
});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,3});
int j = 0;
for(Integer[] i: set){
System.out.println("\nElements: "+j);
j++;
for(Integer k : i){
System.out.print(k+" ");
}
}
}
You need to use Comparator to compare two elements of same. As we don't have comparator for Array, Set will use actual object to compare.. using comparator you will have to tell set that this two arrays are same and do not add other same array
Try Table collection in Google-guava.
Example :
Table<Integer, Integer, Integer[]> sampleTable = HashBasedTable.create();
sampleTable.put(1, 10, new Integer[] { 1,10 });
sampleTable.put(2, 10, new Integer[] { 2,10 });
sampleTable.put(1, 10, new Integer[] { 1,10 });
So it will overwrite the duplicate values. Finally you have only unique values.

How can you check if a sublist is in a certain "window" of a larger list?

Given an arraylist and two start and end indexes, how can you check if a certain sub-ArrayList is present in the "window" i.e. between the indexes.
i.e.
private ArrayList<Character> list = new ArrayList<Character>;
private int start = 2, end = 6;
private ArrayList<Character> sublist = new ArrayList<Character>;
boolean present = isPresent();
How can I implement this isPresent() method efficiently? I will be using this method inside
a run-time encoding algorithm, to compress a text file (it's required I read it into an ArrayList first).
return Collections.indexOfSubList(list.subList(start, end), subList) != -1;
I hope this is what you are looking for
boolean iPresent(List l1, int start, int end, List l2) {
for (int i = start; i < end; i++) {
if (l2.size() > end - i) {
break;
}
if (l1.get(i).equals(l2.get(0))) {
return l1.subList(i, i + l2.size()).equals(l2);
}
}
return false;
}
Note that subList() returns a List backed by its parent list and does not create a new array, no need to worry about performance.

What data structure is most suitable for implementing a 2-D array in Java?

I want to implement a 2-D array kind of a thing.
What data structure will be most suitable for this? An array or some other data-structure will do. If there is any other data structure which will satisfy my requirement, then please tell me.
I don't want to use an array because the 2-D array needs to be declared early in the program but it is not fixed; the size will be determined at run time.
Also, the number of rows will be equal to the number of columns; this is fixed, because the same name will be given to both the rows and the columns.
I also want to traverse through this 2-D data structure as I would through a Map.
It sounds like you want to use a row-key, a col-key, and then the value at that location. There's no builtin data structure that'll do that for you.
The easiest thing to use may be a 2d array for the actual data. Use something like the following to go from a row or column name to the actual index in your array. Add as many name-to-index bindings as you want.
Map<String, Integer> rows = new HashMap<String, Integer>();
Map<String, Integer> cols = new HashMap<String, Integer>();
Then getting that value in the grid...
grid[rows.get("Row name")][cols.get("Column name")];
Put the grid and a get(String rowName, String colName) method in a class if you want a cleaner API.
Edit: I see the question has been updated, and it looks like the name-to-index pairs are the same for both rows and columns. So here's an updated version:
class SquareMap<V> {
private V[][] grid;
private Map<String, Integer> indexes;
public SquareMap(int size) {
grid = (V[][]) new Object[size][size];
indexes = new HashMap<String, Integer>();
}
public void setIndex(String name, int index) {
indexes.put(name, index);
}
public void set(String row, String col, V value) {
grid[indexes.get(row)][indexes.get(col)] = value;
}
public V get(String row, String col) {
return grid[indexes.get(row)][indexes.get(col)];
}
}
(Edits based on comment)
If the size is determined at runtime that is not an issue. This might work:
final int[][] data;
final int size;
final Map<String, Integer> names;
// code that sets the size variable
names = new HashMap<String, Integer>();
data = new int[size][size];
names.put("ID-A", 0);
names.put("ID-B", 1);
data[names.get("ID-A")][names.get("ID-A")] = 39;
data[names.get("ID-A")][names.get("ID-B")] = 40;
data[names.get("ID-B")][names.get("ID-A")] = 41;
data[names.get("ID-B")][names.get("ID-B")] = 42;
Arrays can be sized at runtime. If you have a row/column size that doesn't vary too often, and the data is not too sparse, then an array is your best bet.
class TwoDimArray {
public int[][] createArray(int nRows, int nCols) {
return new int[nRows][nCols];
}
public int[][] resizeArray(int[][] oldArray, int nRows, int nCols) {
int[][] newArray = new int[nRows][nCols];
for (int i=0; i<Math.min(oldArray.length, nRows); ++i)
for (int j=0; j<Math.min(oldArray[i].length, nCols); ++j)
newArray[i][j] = oldArray[i][j];
return newArray;
}
}
You could just use a Map like
class TwoDArray<V> implements Iterable<Map.Entry<Point, V>> {
private final Map<Point, V> map = new LinkedHashMap<Point, V>();
public V set(int x, int y, V value) {
return map.put(new Point(x,y), value);
}
public V get(int x, int y) {
return map.get(new Point(x, y));
}
public Iterator<Map.Entry<Point, V>> iterator() {
return map.entrySet().iterator();
}
}
// to iterate
TwoDArray<Double> twoDArray = new TwoDArray();
twoDArray.set(3, 5, 56.0);
twoDArray.set(-1000, 5, 123.4);
twoDArray.set(789012345, -100000000, -156.9);
for(Map.Entry<Point, Double> entry: twoDArray) {
//
}

Categories

Resources