In an array of arraylists, get the largest arraylist - java

I have an array with multiple arraylists of different sizes.
I want to find the index of the largest arraylist in the array. I tried this:
Collections.max(disc);
disc being the name of the array of arraylists.
ArrayList I believe doesn't implement the Comparable interface so I can't do it like this. Is there a way to make a custom comparable for sizes of ArrayLists?

If you want to know the index of the largest sub-ArrayList then you're basically looking for an information relative to where the largest ArrayList is stored. This research is not based solely on the intrinsic characteristics of your biggest ArrayList but also on where it is located.
Using Collections.max won't help you, even if you redefine its natural ordering providing a new Comparator, because you would only get the largest ArrayList not the index where it is stored. If you want to find the index you have to manually loop the outer ArrayList and whenever you find a new largest sub-ArrayList save its index.
Of course, all of what I said is based on the sole condition that you're interested in retrieving the index and not the biggest sub-ArrayList itself. If you're simply looking for the biggest sub-ArrayList then Collections.max with a Comparator implementation is what you need.

You can't add interfaces to an existing class. If you want ArrayList to implement Comparable, you'll need to write an adaptor class that contains an ArrayList and implements the interface.
But, in your case, you don't need that. Comparable has a sister interface called Comparator which is an external object specifying how to compare some type. It can be used to provide alternative sorting mechanisms (descending rather than ascending, for instance) or, as in your case, to add comparison capabilities to an existing class that lacks them. And Collections.max has an overload that takes a comparator.
Collections.max(disc, (a, b) -> a.size() - b.size())
Note that if you're on a really old Java version, you'll need to explicitly create a Comparator instance, rather than using SAM conversion like I do above.

I want to find the index of the largest arraylist in the array.
Collections.max does not take an array nor does it return an index. It returns the large element in a Collection.
Without knowing your exact data structure I am using a list of lists.
List<List<Integer>> ss =
List.of(
List.of(1, 2, 3),
List.of(1, 2, 3, 4),
List.of(1, 2)
);
This just compares the sizes and returns the index that targets the maximum list
int maxIndex = IntStream.range(0, ss.size()).boxed().collect(Collectors
.maxBy(Comparator.comparing(i -> ss.get(i).size()))).get();
prints
1
The maxBy Collector returns an Optional of which I immediately took the value. You may want to assign it to an Optional and then process appropriately for an empty collection.
A simpler way of doing it is with a loop. Just find the max size and associate the index with it.
maxIndex = 0;
int maxSize = 0;
for (int i = 0; i < ss.size(); i++) {
int size = ss.get(i).size();
if (size> maxSize) {
maxIndex = i;
maxSize = size;
}
}
System.out.println(maxIndex);
prints
1

I prefer the more clever solution by WJS, but here is another solution as well. This one here is not as brief but might be easier to comprehend on first reading.
You said:
I have an array with multiple arraylists of different sizes. I want to find the index of the largest arraylist in the array.
As they discussed, Collections.max returns you a reference to the largest object, not the the index of that object within the array.
So we need two steps:
Determine the largest element.
Get the index of that largest object.
First, some example data.
List[] arrayOfListsOfIntegers =
List.of(
List.of( 1 ) ,
List.of( 1001 , 1002 , 1003 , 1004 ) ,
List.of( 101 , 102 , 103 ) ,
List.of( 11 , 12 )
)
.toArray( List[] :: new );
Determine the largest element
Use Arrays.asList to make a view onto that array that appears as a List. This way we can call convenient List methods.
Then make a stream of that list. Sort the elements of the stream by getting each one’s size. Make a new list from the sorted elements. We know the last element of that sorted list has the biggest element.
List sorted =
Arrays
.asList( arrayOfListsOfIntegers )
.stream()
.sorted( Comparator.comparingInt( List :: size ) )
.toList();
Get a reference to that biggest element, the last element of our sorted list of lists.
Object target = sorted.get( sorted.size() - 1 );
Get the index of that largest object
That target object is what we want to locate within our original list. We can locate by calling List#indexOf. Here again we use Arrays.asList to mask our array as a List.
int index = Arrays.asList( arrayOfListsOfIntegers ).indexOf( target );

Related

How to get first or last item from cqengine IndexedCollection with NavigableIndex

I have com.googlecode.cqengine.IndexedCollection object with NavigableIndex configured. I need to get first or last item from the index or iterator of the index in general.
I suppose this should be trivial. I know I can create Query object with queryOptions object, use it to retrieve iterator from IndexedCollection and get first object, but I'm not sure if it's optimal for performance. Surely it's not elegant.
With help of miradham I figured out that I need to remember indexes, since it's hard to pick up the right one if we have more of them. It will only work with NavigableIndex, we can't iterate base class Index
collection = new ConcurrentIndexedCollection<Data>();
index = NavigableIndex.onAttribute(Data.UNIQUE_TIMESTAMP);
collection.addIndex(index);
when I have the index:
try (CloseableIterator<KeyValue<String, Data>> iterator = indexUniqueTimestamp.getKeysAndValuesDescending(null).iterator()) {
if (iterator.hasNext())
return iterator.next().getValue();
}
return null;
One trick to retrieve the min or max (i.e first or last) object according on one of its attributes, is to use an all() query (which matches all objects in the collection), and to request that results should be returned in ascending or descending order of your attribute.
For example, if you had a collection of Car objects, you could use the following code to retrieve the car which has the highest (i.e. the max) price:
try (ResultSet<Car> results = cars.retrieve(
all(Car.class),
queryOptions(
orderBy(descending(Car.PRICE)),
applyThresholds(
threshold(INDEX_ORDERING_SELECTIVITY, 1.0)
)
))) {
results.stream()
.limit(1)
.forEach(System.out::println);
}
You can also change the limit to something other than 1, in case you want the top n most expensive cars to be returned.
The code above will work regardless of whether or not you actually have a NavigableIndex on the price. The bit about INDEX_ORDERING_SELECTIVITY is to actually request CQEngine to leverage the index (more details here).
or iterator of the index in general
You can use getIndexes() API of QueryEngine interface to retrieve set of Indexes.
Example code:
IndexedCollection<Car> indexedCollection = new ConcurrentIndexedCollection<Car>();
indexedCollection.addIndex(HashIndex.onAttribute(Car.CAR_ID), noQueryOptions());
List<Index<Car>> indexes = new ArrayList<Index<Car>>();
for (Index<Car> index : indexedCollection.getIndexes()) {
indexes.add(index);
}
NavigableIndex stores object in element in Map with attribute as key and set of object as value.
NavigableIndex does not maintain insertion order. First element of the index could be anything.
CQEngine is best designed for random access of object in collection not sequential.
Normal collections in java is best suited for sequence access with index.
one elegant way of accessing first element is to create SequentialIndex class and add it to concurrent collection. retrieve element using index as query.

Is there a list implementation that would allow gaps?

I'm looking for a collection that would be some sort of a list that allows gaps. The objectives are:
every element has some index in the collection that is meaningful.
the collection is to be sparse and not continuous; its size should return the number of proper elements, hence the workaround of initializing with null wouldn't work.
subList method is desirable to access sublists according to index intervals
Sample use case:
List<Integer> list = /* ? */;
list.add(0,5);
list.add(1,4);
list.add(5,3);
for( Integer i : list )
{
System.out.print( i + " " );
}
/* desired output : "5 4 3 "*/
Use a Map<Integer,Integer>. The key would be your index and the value the value of the list.
For your subList requirement, perhaps TreeMap<Integer,Integer> would work, as it keeps the keys sorted and makes it easy to iterate over a sub-list.
Of course this means you can't use the List interface. If you must use the List interface, you can make your own List implementation backed by a TreeMap (for example, list.add(5,3) would call map.put(5,3)).
You may use a Map and only set the keys you need.
You can keep the insertion order if you want, take a look: Java Class that implements Map and keeps insertion order

Index based subset of SortedSet

I need to add objects from a sourceList to a collection that sorts the collection as we add objects to the collection. I am thinking of using TreeSet.
TreeSet bookSet
Based on certain conditions, I need to take subset of the bookSet. Subset will be first N elements. The value of N is known only after entire bookSet is prepared from another sourceList.
Is there anyway I can get the subset of bookSet using index N, Similar to arrayList.subList(0,N).
I can use headSet, but I need to know N+1 th element.
Depending on what your trying to achieve:
You can use the TreeSet.iterator() and iterate N times.
In Java 8 you can use bookSet.stream().limit(N)
You can simply copy to an new ArrayList(bookSet) and then take a subList

Going though a Map specifically a LinkedHashMap and retrieving both Key and Value using ForEach loop reversed

At the moment I'm looping though a list of messages that have the value of importance and the string of the message it's self using:
for(String MessageItem : MainEngine.mCurrentLevel.mNewsFeed.mMessageList.keySet())
{
//Do message stuff here.
}
I have a problem in that only 10 messages can be displayed on screen and it needs to be from the most recent. Problem with the above is that it only shows from index 0 - 10. and no more.
Is there anyway to start from the top index and go in reverse using foreach?
You cannot directly iterate a LinkedHashMap in reverse order. The APIs don't allow it.
The best you can do is copy the keys (or the key/value pairs) to an array and then iterate the array in reverse order.
(Writing the code is simple ... and I encourage you to do it yourself!)
You don't have to iterate through it. But it would be handy to pull the keys off and store it in a list. Thats the only way you can do indexOf() type operations.
List<String> keyList = new ArrayList<String>(map.keySet());
// Given 10th element's key
String key = "aKey";
int idx = keyList.indexOf(key);
for ( int i = idx ; i >= 0 ; i-- )
System.out.println(map.get(keyList.get(i)));
for more details see answer by Kal

How to delete one value from, and decrease the length of, a String array

I don't understand how to decrease the length of a String array. For example, with this code:
String[][] array = new String[5][2];
array[1][0] = "what";
array[2][0] = "is";
.....
.....
array[5][0] = "?";
How can I delete array[5][0] and get array.length to be 4, not 5?
If you want to remove the array element from the end , you can also use Arrays.copyOf() since jdk 1.6+
For example:
array = Arrays.copyOf(array, 4);
It just copy the original array 's first 4 elements to a new array , so it have the same effect as deleting the array[5]
If you want to remove an element from an specified index , you can use ArrayUtils.remove() from Apache Commons Lang 3 to do it .
/**Remove the element at index 3**/
array =ArrayUtils.remove(array, 3);
You cannot delete an item from an array.
But you can create a new array with smaller size and copy the content of the old array to the new one. Then, assign the value of the reference to the new array.
Consider using java.util.List. It has a method remove().
Using arrays for such things is very time consuming. I can suggest these solutions:
1. Use one of the data structures provided by Java libraries. I'd go with HashMap since its structure allows mapping a value to a key (HashMap ) and it does the part of adding, finding and removing items. You can also use them for multi-level hashmaps if you need more than 2 columns (HashMap ) you can look that up.
2. Use a List or ArrayList structure. Make a list that contains arrays or a special structure you create to store your data.
3. (Not recommended) Go for the manual route. If you have a fixed-length array, you can shift the rows back to remove that row, and use an index to define the last row. If you have a dynamic-length array you'll need to reconstruct it each time you remove a row.

Categories