Select positives from a list with Generics - java

I am pretty new here, so excuse me if you do not understand my question.(Be nice :D)
So basically I have to make a method which select positives "numbers" from a list using Generics.
The base of the method should look like this :
public static <T> List<T> selectPositives(List<? extends Number> list) {
T positiveNumber = null;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) > 0) {
return (List<T>) positiveNumber;
}
}
return (List<T>) positiveNumber;
}
Well obviously this is not working, so I would greatly appreciate any help.
Thanks,
Alma

Using Stream API, the list of positives may be filtered out of the input:
public static <T extends Number> List<T> selectPositives(List<T> list) {
return list.stream()
.filter(x -> x.doubleValue() > 0.0)
.collect(Collectors.toList());
}
Also, List::removeIf with inverted condition may be applied to the given input/mutable copy of the input:
public static <T extends Number> List<T> selectPositives(List<T> list) {
List<T> result = new ArrayList<>(list);
result.removeIf(x -> x.doubleValue() <= 0);
return result;
}

I modified your code so that it would return a list of positive numbers.
//public static <T> List<T> selectPositives(List<? extends Number> list) {
public static <T extends Number> List<T> selectPositives(List<T> list) {
//T positiveNumber = null;
List<T> positiveNumbers = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).doubleValue() > 0) {
//return (List<T>) positiveNumber;
positiveNumbers.add(list.get(i));
}
}
return positiveNumbers;
}
public static void main(String[] args) {
List<Number> list = List.of(-1,-2,1.5, 3,-4,-5, 6);
System.out.println(selectPositives(list));
}
Output:
[1.5, 3, 6]

check for absolute value of the number, then compare it to the number without abs. if they match, then it's positive, and if not its negative.
add the elements that match to another list to have all the positive numbers in the list

Related

Java error java: incompatible types: void cannot be converted to java.util.List<java.lang.Integer> when trying to sort list using Collections.sort()

I am trying to return the sorted version of arrnew but it keeps giving me an error on the part Collections.sort(arrnew). My goal of this code is to accept a variable n .I find all factorial numbers of n and find prime factors of those numbers and add it to the array.
import java.util.List;
import java.util.*;
import java.io.*;
public class test2 {
public static List<Integer> factorFactorial(int n) {
ArrayList<Integer> arrnew = new ArrayList<>();
while(n>0) {
int x=n;
for (int i = 2; i <= x ; i++) {
while (x % i == 0) {
arrnew.add(i);
x = x / i;
}
}
n--;
}
;
return Collections.sort(arrnew);
}
public static void main(String[] args) {
List<Integer>a=factorFactorial(10);
for(int x:a){
System.out.print(x);
}
}
}
Collections.sort() returns void, but you have specified your method should return a list. You can simply change your code to return the sorted list:
Collections.sort(arrnew)
return arrnew;
The Collections.sort signature is public static <T extends Comparable<? super T>> void sort​(List<T> list), so as it is void it doesn't return the given list, you have to split it in
Collections.sort(arrnew)
return arrnew;
Or using Stream you can inline it and return a new list object
return arrnew.stream().sorted().collect(Collectors.toList());

Convert from List<List<? extends Object>> to List<List<SpecificType>>

There is my problem, I've a function listToSublists I absolutely want to be generic so i've wrote this :
public static List<List<? extends Object>> listToSubLists(List<? extends Object> elements, int sublistsLength) {
....
}
And i want to call that function that way :
List<LigneMaj> datas = ...;
List<List<LigneMaj>> datasPaquets = BatchUtils.listToSubLists(datas, 100);
It appears that it is impossible to compile and I'm struggling to understand why i'm getting this error :
Type mismatch: cannot convert from List<List<? extends Object>> to List<List<LigneMaj>>
Could someone explain what I am missing please?
public static <T> List<List<T>> listToSubLists(List<T> elements, int sublistsLength) {
if (!elements.isEmpty()) {
List<List<T>> result = new ArrayList<>();
final int sublists = ((elements.size() - 1) / sublistsLength) + 1;
for (int i = 0; i < sublists; i++) {
result.add(new ArrayList<>());
}
for (int currentIndex = 0; currentIndex < elements.size(); currentIndex++) {
final T elem = elements.get(currentIndex);
result.get(currentIndex / sublistsLength).add(elem);
}
return result;
} else {
return Collections.emptyList();
}
}

Why am I getting the error "bad operand types for binary operator" in my methods?

public class t<T extends Number>{
private ArrayList<T> a = new ArrayList<T>();
public void add(T x){
a.add(x);
}
public T largest(){
T large = a.get(0);
int count = 1;
while(a.get(count)!=null){
if(a.get(count)>large)
large = a.get(count);
count++;
}
return large;
}
public T smallest(){
T small = a.get(0);
int count = 1;
while(a.get(count)!=null){
if(a.get(count)<small)
small = a.get(count);
count++;
}
return small;
}
}
I am receiving the error in my if statements within my largest and smallest methods. I've had no luck in troubleshooting the error. Please help. Thank you very much.
a.get(int) isn't convertible to a primitive numeric type (it's Number, in general, which can't be auto-unboxed), so you can't use < or >.
You will need to provide an explicit Comparator<T> (or, more generally, Comparator<? super T>), to allow you to compare elements of the list:
public class t<T extends Number>{
private Comparator<? super T> comparator;
t(Comparator<? super T> comparator) {
this.comparator = comparator;
}
public T largest(){
// ...
if (comparator.compare(a.get(count), large) > 0) {
// ...
}
// ...
}
}

Create random values of generic type in Java

I have the following:
public class RandomList {
private List<Integer> list;
public List<Integer> getList() {
return list;
}
public RandomList (int n) {
list = new ArrayList<Integer>();
Random rand = new Random();
rand.setSeed(System.currentTimeMillis());
for (int i=0; i < n; i++)
{
Integer r = rand.nextInt();
list.add(r);
}
}
}
which gives me a list filled with random Integer values. I would like to generalize this, to also get a list of random Character values or perhaps lists of other types' random values.
So what I want is a generic type version, class RandomList<T>. I can replace everywhere "Integer" by "T", but am stuck at the line Integer r = rand.nextInt(); which would read different for different types.
I am thinking of doing the following:
pass in the class of the generic type to RandomList
using instanceof check the passed in class against the desired types (Integer, Character...) and depending on the check return the proper random value
Does this make sense? Is there another/better way to achieve what I want?
First method (inferior)
In Java you can't check for the generic type, at least not without reflection. You're on the money with the generic type, so you'd do something like this:
public class RandomList<T> {
private List<T> list;
private Class<T> clazz;
public List<T> getList() {
return list;
}
public RandomList (Class<T> clazz, int n) {
this.clazz = clazz;
list = new ArrayList<T>();
Random rand = new Random();
rand.setSeed(System.currentTimeMillis());
if (clazz.isAssignableFrom(Integer.class)) {
for (int i = 0; i < n; i++) {
Integer r = rand.nextInt();
list.add(r);
}
}
else {
throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
}
}
}
Second method (superior)
Alternatively, you could generalise this even further and add a Function to produce the randomised results. Note that this requires Java 8. If you're not on Java 8, you could just define an interface and construct that anonymously.
public class RandomList<T> {
private List<T> list;
public List<T> getList() {
return list;
}
public RandomList (Function<Random, T> creator, int n) {
list = new ArrayList<T>();
Random rand = new Random();
rand.setSeed(System.currentTimeMillis());
for (int i = 0; i < n; i++) {
list.add(creator.apply(rand));
}
}
}
Construct a new instance using:
RandomList<Integer> list = new RandomList<>(rand -> rand.nextInt(), 10);
Third method (cleaner)
Edit: This occurred to me later, but you seem to be using Java 8, so you could just use streams:
List<Integer> list = Stream.generate(() -> rand.nextInt()).limit(10).collect(Collectors.toList())

The best way to find out the biggest length

I have fours variables that call different methods:
public String[] longestSide(){
ArrayList<T> western = getWestern();
ArrayList<T> eastern = getEastern();
ArrayList<T> northern = getNorthern();
ArrayList<T> southern = getSouthern();
return //theLongestOne??
}
Instead of writing a bunch of if-else statements, what is the shortcut to find out which of the arraylists has the longest length and return it? Thanks!
return Collections.max(Arrays.asList(western, eastern, northern, southern),
(a, b) -> Integer.compare(a.length, b.length));
If not on Java 8 yet, the same code can be written as
return Collections.max(Arrays.asList(western, eastern, northern, southern),
new Comparator<String[]> {
#Override
public int compare(String[] a, String[] b) {
return Integer.compare(a.length, b.length));
}
});
If what you have is in fact 4 List<String>, and not 4 arrays as in the original question, then it's even simpler:
return Collections.max(Arrays.asList(western, eastern, northern, southern),
Comparator.comparing(List::size));
which is equivalent to
return Collections.max(Arrays.asList(western, eastern, northern, southern),
new Comparator<List<String>> {
#Override
public int compare(List<String> a, List<String> b) {
return Integer.compare(a.size(), b.size());
}
});
Define a method as follows:
public Sting[] longestOf(String[] a, String[] b){
if(a.length>b.length) {
return a;
}
return b;
}
Now, you can do the following in your longestSide() method:
return longestOf(longestOf(western, eastern), longestOf(northern, southern));
String maxLength = Math.max(Math.max(western.length, eastern.length), Math.max(southern.length, northern.length));
String[] longest =
western.length == maxLength ? western :
eastern.length == maxLength ? eastern :
southern.length == maxLength ? southern :
northern;
return Collections.max(Arrays.asList(getWestern(), getEastern(), getNorthern(), getSouthern()), new Comparator<String[]>() {
#Override
public int compare(String[] first, String[] second) {
return first.length - second.length;
}
});
You can do it in another way.There can be some compilation problem, but the general idea is clear:
private List<T> longest;
// Decorator method, which will return array list, but will also calculate required longest direction.
public <T> List<T> calculateAndGet(List<T> list) {
if (Objects.isNull(longest) || longest.size() < list.size()) {
longest = list.size();
}
return list;
}
public String[] longestSide(){
List<T> western = calculateAndGet(getWestern());
List<T> eastern = calculateAndGet(getEastern());
List<T> northern = calculateAndGet(getNorthern());
List<T> southern = calculateAndGet(getSouthern());
return longest.toArray(new String[longest.size()]);
}
I also changed ArrayList to List. Is there any specific logic not to use "Coding to interfaces" principle?
Implementing as suggested by Shai in a comment:
public String[] longestSide(){
String[] western = getWestern();
String[] eastern = getEastern();
String[] northern = getNorthern();
String[] southern = getSouthern();
String[] longest = null;
for (String[] a : new String[][] {western,eastern,northern,southern})
if (longest == null || a.length > longest.length)
longest = a;
return longest;
}
Or using a helper method for a List (or other Collection) as indicated by updated question:
#SafeVarargs
public static <L extends Collection<?>> L longestOf(L ... lists) {
L longest = lists[0];
for (int i = 1; i < lists.length; i++)
if (lists[i].size() > longest.size())
longest = lists[i];
return longest;
}
Use like this:
return longestOf(western, eastern, northern, southern);

Categories

Resources