001/* 002 * Java Genetic Algorithm Library (jenetics-8.3.0). 003 * Copyright (c) 2007-2025 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.util; 021 022import static java.lang.String.format; 023 024import java.io.Serializable; 025import java.util.Optional; 026import java.util.stream.IntStream; 027 028/** 029 * Integer range class. 030 * 031 * @param min the minimum value of the range 032 * @param max the maximum value of the range 033 * 034 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 035 * @version 8.3 036 * @since 3.2 037 */ 038public record IntRange(int min, int max) implements Serializable { 039 040 /** 041 * Create a new range instance. 042 * 043 * @param min the minimum value of the range 044 * @param max the maximum value of the range 045 * @throws IllegalArgumentException if {@code min > max} 046 */ 047 public IntRange { 048 if (min > max) { 049 throw new IllegalArgumentException(format( 050 "Min greater than max: %s > %s", min, max 051 )); 052 } 053 } 054 055 /** 056 * Create a new (half-open) range, which contains only the given value: 057 * {@code [value, value + 1)}. 058 * 059 * @param value the value of the created (half-open) integer range 060 */ 061 public IntRange(final int value) { 062 this(value, value + 1); 063 } 064 065 /** 066 * Checks whether the given {@code value} is within the range 067 * {@code [min, max)}. 068 * 069 * @since 8.0 070 * 071 * @param value the value to check 072 * @return {@code true} if the {@code value} is with the range 073 * {@code [min, max)}, {@code false} otherwise 074 */ 075 public boolean contains(final int value) { 076 return value >= min && value < max; 077 } 078 079 /** 080 * Return the intersection of {@code this} range with the {@code other}. 081 * 082 * @since 8.0 083 * 084 * @param other the intersection range or {@link Optional#empty()} if there 085 * is none 086 * @return the range intersection 087 */ 088 public Optional<IntRange> intersect(final IntRange other) { 089 if (max <= other.min || min >= other.max) { 090 return Optional.empty(); 091 } else { 092 return Optional.of( 093 new IntRange( 094 Math.max(min, other.min), 095 Math.min(max, other.max) 096 ) 097 ); 098 } 099 } 100 101 /** 102 * Return the size of the {@code IntRange}: {@code max - min}. 103 * 104 * @since 3.9 105 * 106 * @return the size of the int range 107 */ 108 public int size() { 109 return max - min; 110 } 111 112 /** 113 * Returns a sequential ordered {@code IntStream} from {@link #min()} 114 * (inclusive) to {@link #max()} (exclusive) by an incremental step of 115 * {@code 1}. 116 * <p> 117 * An equivalent sequence of increasing values can be produced sequentially 118 * using a {@code for} loop as follows: 119 * {@snippet lang="java": 120 * for (int i = range.min(); i < range.max(); ++i) { 121 * // ... 122 * } 123 * } 124 * 125 * @since 3.4 126 * 127 * @return a sequential {@link IntStream} for the range of {@code int} 128 * elements 129 */ 130 public IntStream stream() { 131 return IntStream.range(min, max); 132 } 133 134 /** 135 * Create a new {@code IntRange} object with the given {@code min} and 136 * {@code max} values. 137 * 138 * @param min the lower bound of the integer range 139 * @param max the upper bound of the integer range 140 * @return a new {@code IntRange} object 141 * @throws IllegalArgumentException if {@code min > max} 142 * 143 * @deprecated Class is a record now, and this factory method will be 144 * removed in the next major version. Use {@link #IntRange(int, int)} 145 * instead. 146 */ 147 @Deprecated(since = "8.2", forRemoval = true) 148 public static IntRange of(final int min, final int max) { 149 return new IntRange(min, max); 150 } 151 152 /** 153 * Return a new (half-open) range, which contains only the given value: 154 * {@code [value, value + 1)}. 155 * 156 * @since 4.0 157 * 158 * @param value the value of the created (half-open) integer range 159 * @return a new (half-open) range, which contains only the given value 160 * 161 * @deprecated Class is a record now, and this factory method will be 162 * removed in the next major version. Use {@link #IntRange(int)} 163 * instead. 164 */ 165 @Deprecated(since = "8.2", forRemoval = true) 166 public static IntRange of(final int value) { 167 return of(value, value + 1); 168 } 169 170 @Override 171 public String toString() { 172 return "[" + min + ", " + max + "]"; 173 } 174 175}